C#的WaitHandle取消了WaitAll [英] C# WaitHandle cancelable WaitAll

查看:214
本文介绍了C#的WaitHandle取消了WaitAll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的代码,有目标,以等待所有给定的等待句柄,但撤销的由一个特定的等待句柄:

I have the following code which has the goal to wait for all given wait handles but is cancellable by a specific wait handle:

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事件。当使用了WaitAny重置所有信号事件,但返回自动复位事件只有第一个信号(根据MSDN)。

This works only for ManualReset events. When using AutoReset events WaitAny resets all signalled events but returns only the first signalled (according MSDN).

任何想法如何得到这个具有自动复位事件做以适当的方式,而不投票?

Any ideas how to get this done with AutoReset events in a proper way without polling?

推荐答案

我觉得你的方法应该正常工作作为编写的。

I think that your method should work correctly as-written.

我相信WaitHandle.WaitAny()使用的 Windows API函数WaitForMultipleObjects的(),为此,文件说:

I believe that WaitHandle.WaitAny() uses the Windows API function WaitForMultipleObjects(), the documentation for which says:

修改只针对发生对象或对象的信号状态导致函数返回。

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

如果属实,这意味着你的代码应该工作。

If true, it means that your code should work.

我写了一个测试程序。它创建AutoResetEvents的负载,并将其中的一半调用CancelableWaitAll()之前。然后开始在设定AutoResetEvents的另一半之前等待5秒的线程。启动线程后不久,主线程调用CancelableWaitAll()。

I wrote a test program. It creates a load of AutoResetEvents and sets half of them before calling CancelableWaitAll(). Then it starts a thread that waits 5 seconds before setting the other half of the AutoResetEvents. Immediately after starting that thread, the main thread calls CancelableWaitAll().

如果在了WaitAny()实际上重置任何比其索引被返回的其他自动复位的事件,该CancelableWaitAll()将不会返回

If the WaitAny() actually reset any of the autoreset events other than the one whose index was returned, the CancelableWaitAll() would never return.

由于它不返回(5秒,当然之后),我断言你的代码与AutoResetEvents:

Because it does return (after 5 seconds of course), I'm asserting that your code works with 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得到在OS事件处理和使用的P / Invoke调用WaitForMultipleObjects的()。

Unfortunately, I can't prove that WaitHandle.WaitAll() uses WaitForMultipleObjects(). However, if it didn't, you could call it yourself by using WaitHandle.SafeWaitHandle to get at the OS event handles and use P/Invoke to call WaitForMultipleObjects().

这篇关于C#的WaitHandle取消了WaitAll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆