在另一个线程上处理manualResetevent

时间:2017-10-04 19:35:55

标签: c# multithreading

this question类似,我有一个带有私有ManualReset事件的类:

class A {
       private ManualResetEvent mre = new ManualResetEvent(true);
       private void Method(){
            //do something
            mre.Reset();
       }      
       public bool WaitForItem(int timeout){
           try{
               return mre.WaitOne(timeout)
           }catch(ObjectDisposedException){
               return false;
           }
      }
      public void Dispose(){
           mre.Dispose();
      }
}

如何在调用Dispose时检查WaitForItem方法返回false,并且不会阻止等待。

代码类似于:

   A a = new A(1);
   a.Method();
   bool finished = true;
   Thread t1 = new Thread(() =>
   {
       finished = a.WaitForItem(Timeout.Infinite);
   });
   Thread t2 = new Thread(() =>
   {
       a.Dispose();
   });
   t1.Start();
   t2.Start();
   t1.Join();
   t2.Join();

代码阻止永远等待项目(t1.Join())。我理解调用Close,这也是处理对象的意思,不会影响句柄的状态,但是如何用false退出方法(捕获ObjectDisposedException) ?

尽管不是在第二个线程上调用a.Dispose()而是调用另一个方法来释放ManualResetEvent,但是对WaitOne()的调用被阻止了。

1 个答案:

答案 0 :(得分:1)

仅在调用成员函数之前已经放置了对象时才会引发ObjectDisposedException。在您的情况下不会发生这种情况,因为在mre.WaitOne(timeout)之前调用函数mre.Dispose()

一旦简单修复就可以在具有较短超时值的循环中调用mre.WaitOne(timeout)函数。例如一个人希望10 seconds函数有WaitForItem超时,然后只需1秒超时即可调用mre.WaitOne(timeout),并且会在10次尝试后放弃。

下面将解释WaitForItem功能的典型实现。 WaitForItem有3个可能的返回值。

1 =在mre上触发设置 0 =在指定的超时内未触发设置 -1 =在超时之前处置对象。

public int WaitForItem(int timeout){
   try{
       int nReturnCode = 0;
       int nTimeElapsed = 0;
       while (true)
       {
           if (mre.WaitOne(1000))  //just wait for  1 second
           {
               nReturnCode = 1; //Set call on ManualResetEvent
               break;
           }
           else  //Timeout need to repeat
           {
               nTimeElapsed += 1000;
               if (nTimeElapsed > timeout)
               {
                   nReturnCode = 0; //timeout
                   break;
               }
           }
       }
       return nReturnCode;
   }catch(ObjectDisposedException){
       return -1; //Exception 
   }

}