Dispose WaitHandle for basic thread synchronization

天大地大妈咪最大 提交于 2021-01-28 05:08:40

问题


According to documentation, WaitHandle in .NET should be explicitly/implicitly disposed. However, I'm having trouble achieving this for the following basic synchronization task:

  • a time consuming task is being executed on a thread.
  • the main thread waits for the task to complete for a predefined time-period. The main thread must proceed if a. the task is completed or b. the timeout occurred.

Here my attempt at using an AutoResetEvent object:

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();
    }
}

There is an obvious race condition where the main thread wait times out and disposes the wait handle object which causes ObjectDisposedException exception. Is there any other way that I set this up so that the handle is properly disposed and without causing the exception?


回答1:


Sure, there's no decent way to do this. Do note up front that you painted yourself into that corner by essentially leaving a thread running wild, nothing particularly nice about that.

But you are focusing on the much smaller problem. The Thread class itself is already a resource hog, consuming a megabyte of VM and five synchronization objects. But it has no Dispose() method. This was courageous design, there's just no decent way to call the method.

Disposing is optional, nothing that dramatic happens when you don't call it. The class has got your back, it has a finalizer that ensures that the native operating system resource will be released. Which will run, eventually, just not as quickly as you'd like.

Compare this to a class with a less courageous design, the Task class has a Dispose() method. Which, like Thread, is almost as hard to call. The guidance from the .NET gurus is to just not bother.

Same here.




回答2:


The waithandle is disposing because your using scope invokes a new thread an returns immediately, causing the waithandle to dispose.

What you should do is explicitly call dispose after you finish your work instead of your using statement:

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


来源:https://stackoverflow.com/questions/23039999/dispose-waithandle-for-basic-thread-synchronization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!