2017-10-04 82 views
0

類似this question一個ManualResetEvent的我有一類的私人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()的調用置於阻塞狀態。

+0

你正在運行到這個問題,表明有什麼東西在你的應用程序的設計腥。但是,如果您確實需要這樣做,請嘗試使用'ManualResetEventSlim'並使用[Wait(CancellationToken)](https://msdn.microsoft.com/zh-cn/library/dd321783(v = vs.110).aspx ) 方法。在處理MRE之前,只需更改您的Dispose'方法來設置取消令牌。老實說,你需要重新考慮你的設計。像這樣的東西確實不應該是必要的。 –

回答

1

ObjectDisposedException僅當在調用成員函數之前已經放置了對象時纔會引發。這不會發生在您的案例中,因爲在mre.Dispose()之前調用功能mre.WaitOne(timeout)

一旦簡單修復可能是在具有較短超時值的循環中調用mre.WaitOne(timeout)函數。例如人們希望函數的10 seconds超時,然後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 
    } 

}