是Wait() - 在ManualResetEventSlim上保证取消吗?

时间:2017-10-18 13:01:00

标签: c# .net synchronization cancellation manualresetevent

给出以下代码:

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()同时/以任何顺序发生,因此无论如何都会出现这两种情况"。我完全清楚这一点。

1 个答案:

答案 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检查之间中断第一个线程。