给出以下代码:
CancellationTokenSource cts = new CancellationTokenSource();
ManualResetEventSlim mre = new ManualResetEventSlim();
并且这两个线程并发执行:
mre.Wait(cts.Token);
cts.Cancel();
mre.Set();
是第一个(调用mre.Wait(cts.Token)
)保证投掷OperationCanceledException
,还是只是返回?
我的直觉说我应该发生任何一种情况(内部竞争条件)。 MSDN没有给出答案,它只是说"同时观察CancellationToken"。
我希望得到一个答案,详细说明如何以及为何。
我希望预先排除评论,例如"您应该期望Cancel()
和Set()
同时/以任何顺序发生,因此无论如何都会出现这两种情况"。我完全清楚这一点。
答案 0 :(得分:2)
存在竞争条件,因为Wait
就像implemented那样:
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;
}
第二个线程(取消并设置令牌)可能会在cancellationToken.ThrowIfCancellationRequested()
检查和IsSet
检查之间中断第一个线程。