gpt4 book ai didi

C# WaitHandle 可取消 WaitAll

转载 作者:太空狗 更新时间:2023-10-29 21:58:29 24 4
gpt4 key购买 nike

我有以下代码,其目标是等待所有给定的等待句柄,但可由特定的等待句柄取消:

public static bool CancelableWaitAll(WaitHandle[] waitHandles, WaitHandle cancelWaitHandle)
{
var waitHandleList = new List<WaitHandle>();
waitHandleList.Add(cancelWaitHandle);
waitHandleList.AddRange(waitHandles);
int handleIdx;
do
{
handleIdx = WaitHandle.WaitAny(waitHandleList.ToArray());
waitHandleList.RemoveAt(handleIdx);
}
while (waitHandleList.Count > 1 && handleIdx != 0);
return handleIdx != 0;
}

这仅适用于 ManualReset 事件。使用 AutoReset 事件时,WaitAny 会重置所有发出信号的事件,但仅返回第一个发出信号的事件(根据 MSDN)。

关于如何在不进行轮询的情况下以正确的方式使用 AutoReset 事件完成此操作,您有什么想法吗?

最佳答案

我认为您的方法应该按照所写的那样正确工作。

我相信 WaitHandle.WaitAny() 使用 the Windows API function WaitForMultipleObjects() ,其中的文档说:

Modification occurs only for the object or objects whose signaled state caused the function to return.

如果为真,则意味着您的代码应该可以工作。

我写了一个测试程序。它会创建一个 AutoResetEvent 负载并在调用 CancelableWaitAll() 之前设置其中的一半。然后它启动一个线程,等待 5 秒,然后再设置另一半的 AutoResetEvents。在启动该线程后,主线程立即调用 CancelableWaitAll()。

如果 WaitAny() 实际上重置了除返回其索引的事件之外的任何自动重置事件,则 CancelableWaitAll() 将永远不会返回。

因为它确实返回(当然是在 5 秒后),所以我断言您的代码适用于 AutoResetEvents:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
public static class Program
{
private static void Main(string[] args)
{
AutoResetEvent[] events = new AutoResetEvent[32];

for (int i = 0; i < events.Length; ++i)
{
events[i] = new AutoResetEvent(false);
}

// Set the first 16 auto reset events before calling CancelableWaitAll().

for (int i = 0; i < 16; ++i)
{
events[i].Set();
}

// Start a thread that waits five seconds and then sets the rest of the events.

Task.Factory.StartNew(() => setEvents(events));

Console.WriteLine("Waiting for all events to be set.");

ManualResetEvent stopper = new ManualResetEvent(false);
CancelableWaitAll(events, stopper);

Console.WriteLine("Waited.");
}

private static void setEvents(AutoResetEvent[] events)
{
Thread.Sleep(5000);

for (int i = 16; i < events.Length; ++i)
{
events[i].Set();
}
}

public static bool CancelableWaitAll(WaitHandle[] waitHandles, WaitHandle cancelWaitHandle)
{
var waitHandleList = new List<WaitHandle>();
waitHandleList.Add(cancelWaitHandle);
waitHandleList.AddRange(waitHandles);
int handleIdx;
do
{
handleIdx = WaitHandle.WaitAny(waitHandleList.ToArray());
waitHandleList.RemoveAt(handleIdx);
}
while (waitHandleList.Count > 1 && handleIdx != 0);
return handleIdx != 0;
}
}
}

不幸的是,我无法证明 WaitHandle.WaitAll() 使用 WaitForMultipleObjects()。但是,如果没有,您可以自己调用它,方法是使用 WaitHandle.SafeWaitHandle 获取操作系统事件句柄并使用 P/Invoke 调用 WaitForMultipleObjects()。

关于C# WaitHandle 可取消 WaitAll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15069467/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com