【问题标题】:How to avoid thread waiting in the following or similar scenarios (want to make a thread wait iff its really really necessary)?如何在以下或类似情况下避免线程等待(如果真的有必要让线程等待)?
【发布时间】:2013-03-10 00:18:37
【问题描述】:

请看下面的代码sn-p。我正在尝试执行一个长时间运行的任务,但我不想等待超过给定的超时时间。我想完全控制任务何时开始,因此产生一个新线程并完成工作,并在父线程中等待它。该模式确实有效,但父线程只是在等待。理想情况下,我不喜欢线程休眠/等待,除非它真的需要。我怎样才能做到这一点?欢迎任何建议/想法/模式。

/// <summary>
/// tries to execute a long running task
/// if the task is not completed in specified time, its deemed un-sccessful.
/// </summary>
/// <param name="timeout"></param>
/// <returns></returns>
bool Task(int timeout)
{
    bool workCompletedSuccessfully = false;
    //I am intentionally spawning thread as i want to have control when the thread start
    //so not using thread pool threads.
    Thread t = new Thread(() =>
    {
        //executes some long running task
        //handles all the error conditions
        //ExecuteTask();
        workCompletedSuccessfully = true;
    });
    t.Start();
    //cannot wait more "timeout"                        
    //My main thread (parent) thread simply waiting for the spawened thread to join
    //HOW CAN I AVOID THIS?ANY PATTERN TO AVOID THIS REALLY HELPS?
    t.Join(timeout);
    if (!workCompletedSuccessfully)
    {
        //deeemed un-successful
        //do the remediation by gracefully disposing the thread
        //itnentionally hidden details about disposing thread etc, to concentrate on 
        //the question - AVOIDING PARENT THREAD TO WAIT
    }
    return workCompletedSuccessfully;
}

问候, 梦想家

【问题讨论】:

  • 确切地说,您希望如何优雅地处理尚未完成工作的线程?
  • 无论如何,我不确定您是否可以让您的父线程做一些有意义的事情,并以任何直接的方式接收超时通知。 (也就是说,不让父线程通过可以接收“任务成功”或“任务超时”事件的事件循环工作。)既然,那么,那将如何工作?父线程是否应该被中断并处理通知?
  • @I4V 好主意,但显然需要“异步”整个代码库。 (一个不平凡的改变,但在这里可能是正确的选择。)
  • @millimoose 是的,它要求切换到 TPL 库,但 async/await 不是必须的。

标签: c# .net multithreading


【解决方案1】:

使用AutoResetEvent

bool Task(int timeout)
{
    AutoResetEvent threadFinished = new AutoResetEvent(false);
    //I am intentionally spawning thread as i want to have control when the thread start
    //so not using thread pool threads.
    Thread t = new Thread(() =>
    {
        //executes some long running task
        //handles all the error conditions
        //ExecuteTask();
        threadFinished.Set();
    });
    t.Start();
    //Param - timeout
    bool finished = threadFinished.WaitOne(timeout);
    if (!finished)
    {
        //deeemed un-successful
        //do the remediation by gracefully disposing the thread
    }
    return finished;
}

我在这里看到的唯一问题是您打算如何处理未按时完成的线程。理论上你可以调用Thread.Abort(),但这不是一个好主意,因为它会破坏应用程序的状态。

编辑:您需要了解threadFinished.WaitOne(timeout); 仍处于阻塞状态,但不会超过timeout

【讨论】:

  • 我认为 OP 想要的是摆脱父线程等待 - 即让它继续自己的业务,但也会收到超时发生的通知。
  • @millimoose 也许吧。让我们看看他怎么说。
  • @millimoose 如果这是他真正想要的,他可以将我的代码包装到线程中并启动。
  • 您好安德烈,感谢您的快速回复。但即使是 threadFinished.waitone(timeout) 也会阻塞父线程。不是吗?它只是相同模式的变体并使用事件而不是 thread.join()。换句话说,要避免 thread.join() 或 event.waitone() 因为父线程只是等待什么都不做。问候,梦想家
  • @Dreamer 是的,它正在阻塞。要使其非阻塞,只需在另一个线程中运行我的代码。所以你将有 3 个线程,UI 线程、观察者线程和工作线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-29
  • 2015-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多