配置WaitHandle以进行基本线程同步

时间:2014-04-13 07:27:19

标签: c# multithreading waithandle

根据文档,应明确/隐含地处理.NET中的WaitHandle。但是,我无法在以下基本同步任务中实现此目的:

  • 正在线程上执行耗时的任务。
  • 主线程等待任务完成预定义的时间段。如果a,主线程必须继续。任务完成或b。超时发生了。

这里我尝试使用AutoResetEvent对象:

using(var waitHandle = new AutoResetEvent(false)){
    var worker = new Thread(() =>
    {
        try
        {
            TimeConsumingTask();
            waitHandle.Set(); //throws System.ObjectDisposedException: Safe handle has been closed
        }
        catch (Exception e)
        {...}
    }) {IsBackground = true};
    worker.Start(); //start worker

    const int waitTimeInMs = 5000; 
    var signaled = waitHandle.WaitOne(waitTimeInMs);//block main thread here. 
    if (!signaled)
    { //if timed out
       worker.Interrupt();
    }
}

有一个明显的竞争条件,主线程等待超时并处理导致ObjectDisposedException异常的等待句柄对象。有没有其他方法我设置它以便正确处理句柄,而不会导致异常?

2 个答案:

答案 0 :(得分:4)

当然,没有合适的方法可以做到这一点。请事先注意你自己画了一个角落,基本上留下一个疯狂的线程,没有什么特别好的。

但是你专注于更小的问题。 Thread类本身已经是资源占用,消耗了一兆字节的VM和五个同步对象。但它没有Dispose()方法。这是勇敢的设计,没有合适的方法来调用该方法。

处置可选,当你不打电话时,没有任何戏剧性的事情发生。该类已经退缩,它有一个终结器,可确保释放本机操作系统资源。哪个运行,最终,不会像你一样快。

将此与具有较少勇敢设计的类相比较,Task类具有Dispose()方法。像Thread一样,几乎同样难以调用。 guidance from the .NET gurus只是不打扰。

同样在这里。

答案 1 :(得分:0)

waithandle正在处理,因为你的使用范围调用一个新的线程立即返回,导致waithandle被处置。

您应该做的是在完成工作后明确调用dispose而不是using语句:

waitHandle.WaitOne(waitTimeInMs);
if (!signaled)
{ //if timed out
   worker.Interrupt();
}
waitHandle.Dispose();