Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在另一个线程上处理ManualReset事件_C#_Multithreading - Fatal编程技术网

C# 在另一个线程上处理ManualReset事件

C# 在另一个线程上处理ManualReset事件,c#,multithreading,C#,Multithreading,与之类似,我有一个带有私有ManualReset事件的类: class A { private ManualResetEvent mre = new ManualResetEvent(true); private void Method(){ //do something mre.Reset(); } public bool WaitForItem(int timeout){

与之类似,我有一个带有私有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
时,如何检查方法是否返回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()的调用被阻止。

只有在调用成员函数之前已处理对象时,才会引发
ObjectDisposedException
。这在您的情况下不会发生,因为函数
mre.WaitOne(timeout)
mre.Dispose()之前调用

一个简单的修复方法是在一个具有较短超时值的循环中调用
mre.WaitOne(timeout)
函数。e、 g.如果想让
WaitForItem
函数有
10秒
超时,那么
mre.WaitOne(timeout)
只需1秒超时即可调用,并在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 
   }

}

您遇到这个问题表明您的应用程序设计中存在可疑之处。但如果确实需要这样做,请尝试使用
ManualResetEventSlim
并使用该方法。在处理MRE之前,只需更改
Dispose
方法以设置取消令牌。不过,老实说,你需要重新思考你的设计。这样的事情真的不必要。