Reputation: 919
Similar to this question I have a class with a private ManualReset event:
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();
}
}
How can I check that when Dispose
is called WaitForItem
method returns false, and doesn't block waiting.
The code is something similar to:
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();
The code blocks in waiting an item forever (at t1.Join()
). I understood that calling Close
, which is also a mean of disposing an object, doesn't affect the state of the handle, but how can I exit the method with false (catching an ObjectDisposedException
) ?
Even though instead of calling a.Dispose()
on the second thread calling another method which Disposes the ManualResetEvent the call to WaitOne() it's blocked.
Upvotes: 0
Views: 910
Reputation: 20095
The ObjectDisposedException
is raised only when an object is already disposed before calling a member function. This is not happening in your case as function mre.WaitOne(timeout)
is called before mre.Dispose()
.
Once simple fix could be to call mre.WaitOne(timeout)
function in a loop with a shorter timeout value. e.g. one want to have 10 seconds
timeout for WaitForItem
function then mre.WaitOne(timeout)
can be called with just 1 sec timeout and it will give up after 10 tries.
A typical implementation could for WaitForItem
function is explained below. WaitForItem
has got 3 possible return values.
1 = Set is triggered on mre
0 = Set is not triggered within specified timeout
-1 = Object is dispose before timeout.
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
}
}
Upvotes: 1