Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you close an application when some WaitHandle is in the middle of a call to WaitOne?

Is there a standard way to close out an application "cleanly" while some WaitHandle objects may be in the state of a current blocking call to WaitOne?

For example, there may be a background thread that is spinning along in a method like this:

while (_request.WaitOne())
{
    try
    {
        _workItem.Invoke();
    }
    finally
    {
        OnWorkCompleted();
    }
}

I see no obvious way to dispose of this thread without calling Thread.Abort (which from what I understand is discouraged). Calling Close on the _request object (an AutoResetEvent), however, will throw an exception.

Currently, the thread that is running this loop has its IsBackground property set to true, and so the application appears to close properly. However, since WaitHandle implements IDisposable, I'm unsure if this is considered kosher or if that object really ought to be disposed before the app exits.

Is this a bad design? If not, how is this scenario typically dealt with?

like image 424
Dan Tao Avatar asked Jun 21 '10 19:06

Dan Tao


People also ask

What does WaitOne do?

WaitOne(TimeSpan, Boolean) Blocks the current thread until the current instance receives a signal, using a TimeSpan to specify the time interval and specifying whether to exit the synchronization domain before the wait.


1 Answers

Define an additional WaitHandle called _terminate that will signal a request to terminate the loop and then use WaitHandle.WaitAny instead of WaitHandle.WaitOne.

var handles = { _request, _terminate };
while (WaitHandle.WaitAny(handles) == 0)
{
  try
  {
    _workItem.Invoke();
  }
  finally
  {
    OnCompleteWork();
  }
}
like image 70
Brian Gideon Avatar answered Nov 05 '22 20:11

Brian Gideon