首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# WaitHandle可取消的WaitAll

C# WaitHandle可取消的WaitAll
EN

Stack Overflow用户
提问于 2013-02-25 22:38:18
回答 1查看 1.3K关注 0票数 6

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

代码语言:javascript
复制
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事件吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-02-25 23:17:27

我认为你的方法应该按照原文正确地工作。

我相信WaitHandle.WaitAny()使用the Windows API function WaitForMultipleObjects(),它的文档是这样说的:

修改仅针对其信号状态导致函数返回的一个或多个对象发生。

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

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

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

因为它确实会返回(当然是在5秒之后),所以我断言您的代码可以与AutoResetEvents一起工作:

代码语言:javascript
复制
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()来自己调用它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15069467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档