Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any way to trigger timeout on WaitOne() immediately?

In Microsoft .NET, the method WaitOne()

public virtual bool WaitOne(
TimeSpan timeout
)

will return true if the current instance receives a signal; otherwise, false.

My question is, is there a way to let it return false even if the timeout point has not came yet?
Or
In another words, is there a way to immediately trigger a timeout on WaitOne() even if the real timeout point has not came?

Update:

The project is based on .NET 3.5, so the ManualResetEventSlim may not work (introduced in .NET 4). Thanks @ani anyway.

like image 335
Yuanhang Guo Avatar asked Mar 27 '14 04:03

Yuanhang Guo


2 Answers

You can't cancel the WaitOne but you could wrap it:

public bool Wait(WaitHandle yourEvent, WaitHandle cancelEvent, TimeSpan timeOut)
{
   WaitHandle[] handles = new WaitHandle[] { yourEvent, cancelEvent };

   // WaitAny returns the index of the event that got the signal
   var waitResult = WaitHandle.WaitAny(handles, timeOut);  

   if(waitResult == 1)
   {
       return false; // cancel!
   }

   if(waitResult == WaitHandle.WaitTimeout)
   {
       return false; // timeout
   }

   return true;
}

Just pass the handle you want to wait for and a handle to cancel the waiting and a time out.

Extra

As an extension method so it can be called in a similar way to the WaitOne:

public static bool Wait(this WaitHandle yourEvent, WaitHandle cancelEvent, TimeSpan timeOut)
{
   WaitHandle[] handles = new WaitHandle[] { yourEvent, cancelEvent };

   // WaitAny returns the index of the event that got the signal
   var waitResult = WaitHandle.WaitAny(handles, timeOut);  

   if(waitResult == 1)
   {
       return false; // cancel!
   }

   if(waitResult == WaitHandle.WaitTimeout)
   {
       return false; // timeout
   }

   return true;
}
like image 99
Emond Avatar answered Oct 14 '22 16:10

Emond


It appears you want to wait for a signal for a certain amount of time, while also being able to cancel the wait operation while it is in progress.

One way to achieve this is to use a ManualResetEventSlim together with a cancellation token using the Wait(TimeSpan timeout, CancellationToken cancellationToken) method. In this case, one of three things will happen:

  1. The Wait operation will complete with true as soon as the event is signaled (before the timeout completes).
  2. The Wait operation will complete with false if the event hasn't been signaled at the timeout point.
  3. An OperationCanceledException will be thrown if the cancellation-token is set while the wait operation is in progress.
like image 32
Ani Avatar answered Oct 14 '22 16:10

Ani