0

来自文档(EventWaitHandle.Set

不能保证每次调用 Set 方法都会从重置模式为 EventResetMode.AutoReset 的 EventWaitHandle 中释放线程。如果两个调用靠得太近,以至于第二个调用发生在一个线程被释放之前,那么只有一个线程被释放。就好像第二次通话没有发生一样。此外,如果在没有线程等待且 EventWaitHandle 已发出信号时调用 Set,则该调用无效。

考虑以下代码

private AutoResetEvent _are = new AutoResetEvent(false);

private void AnyMethod()
{
  await _are.Set();
}

情况1

private async Task Method1(long timeout)
{  
  await _are.WaitOneAsync(timeout);
}

private async Task Method2()
{  
  await _are.WaitOneAsync();
}

private static Task WaitOneAsync(this WaitHandle waitHandle, long timeout)
{
    if (waitHandle == null)
        throw new ArgumentNullException("waitHandle");

    var tcs = new TaskCompletionSource<bool>();
    var rwh = ThreadPool.RegisterWaitForSingleObject(waitHandle,
        delegate { tcs.TrySetResult(true); }, null, timeout, true);
    var t = tcs.Task;
    t.ContinueWith( (antecedent) => rwh.Unregister(null));
    return t;
}

案例二


private void Method1(int timeout)
{  
  _are.WaitOne(timeout);
}

private void Method2()
{  
  _are.WaitOne();
}

想象一下,两者Method1Method2被调用,然后AnyMethod在超时时及时释放一个线程Method1

在情况 1 和 2 中是否有关于线程释放的保证,或者Set方法行为通常适用于任何线程释放,当其中任何一个发生在另一个附近时?

4

1 回答 1

1

从医生...

文档引用描述了Set调用时会发生什么并且没有线程等待。您问题的其余部分中的代码都是关于Set在线程等待时调用的,因此文档的该段落不适用。

在情况 1 和 2 中是否有关于线程释放的保证,或者 Set 方法行为通常适用于任何线程释放,当两者靠近另一个时?

是的; 其中一个等待线程将被释放。如果事件Set在超时之前,它可能是任一线程;如果事件Set在超时之后,它将是没有超时的线程。

于 2021-01-23T18:04:02.327 回答