ManualResetEventSlim 上的 Wait()-ing 是否保证在取消时抛出?
Is Wait()-ing on a ManualResetEventSlim guaranteed to throw on cancellation?
给定以下代码:
CancellationTokenSource cts = new CancellationTokenSource();
ManualResetEventSlim mre = new ManualResetEventSlim();
并且这两个线程同时执行:
mre.Wait(cts.Token);
cts.Cancel();
mre.Set();
是第一个(调用 mre.Wait(cts.Token)
)保证 抛出 OperationCanceledException
还是有可能 只是 return?
我的直觉告诉我应该预料到这两种情况都会发生(内部竞争条件)。 MSDN 没有给出答案,它只是说 "while observing the CancellationToken".
我希望得到关于如何以及为什么的具体细节的答案。
我想抢占像 "you should expect Cancel()
and Set()
to occur concurrently / in any order, and thus both cases, anyway" 这样的评论。我完全知道这一点。
存在竞争条件,因为 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
检查之间中断第一个线程。
给定以下代码:
CancellationTokenSource cts = new CancellationTokenSource();
ManualResetEventSlim mre = new ManualResetEventSlim();
并且这两个线程同时执行:
mre.Wait(cts.Token);
cts.Cancel();
mre.Set();
是第一个(调用 mre.Wait(cts.Token)
)保证 抛出 OperationCanceledException
还是有可能 只是 return?
我的直觉告诉我应该预料到这两种情况都会发生(内部竞争条件)。 MSDN 没有给出答案,它只是说 "while observing the CancellationToken".
我希望得到关于如何以及为什么的具体细节的答案。
我想抢占像 "you should expect Cancel()
and Set()
to occur concurrently / in any order, and thus both cases, anyway" 这样的评论。我完全知道这一点。
存在竞争条件,因为 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
检查之间中断第一个线程。