Reputation: 13233
Given the following code:
CancellationTokenSource cts = new CancellationTokenSource();
ManualResetEventSlim mre = new ManualResetEventSlim();
and these two threads executing concurrently:
mre.Wait(cts.Token);
cts.Cancel();
mre.Set();
is the first one (call to mre.Wait(cts.Token)
) guaranteed to throw an OperationCanceledException
or is it also possible that it will just return?
My gut says I should expect either to happen (internal race condition). MSDN does not give an answer, it just says "while observing the CancellationToken".
I'm hoping for an answer with specific details as to how and why.
I would like to pre-empt comments like "you should expect Cancel()
and Set()
to occur concurrently / in any order, and thus both cases, anyway". I'm fully aware of that.
Upvotes: 3
Views: 809
Reputation: 101483
There is race condition because Wait
is implemented like that:
public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
{
ThrowIfDisposed();
cancellationToken.ThrowIfCancellationRequested(); // an early convenience check
if (millisecondsTimeout < -1)
{
throw new ArgumentOutOfRangeException("millisecondsTimeout");
}
if (!IsSet)
{
// lots of stuff here, not relevant
}
return true;
}
Second thread (which both cancels and sets the token) might interrupt first thread right between cancellationToken.ThrowIfCancellationRequested()
check and IsSet
check.
Upvotes: 2