如何在C#中以取消支持在c#中等待多个Waithandle数组



c#具有推荐的方法,可以通过ThreadPool.RegisterWaitForSingleObject以非阻滞方式等待单个Waithandle对象。但是我需要类似的东西,但对于多个对象。类似于WaitHandle.WaitAll,但在异步变体中。如何以更少的资源浪费方式实现这一目标?现在,我考虑创建任务并在那里等待手柄,类似的东西:

public static class WaitHandleExtension
{
    public static Task<bool> WaitAllAsync ( this WaitHandle[] handles )
    {
        return Task.Factory.StartNew( () => WaitHandle.WaitAll( handles ) );
    }
}

,但我无法以这种方法实施取消。通过取消支持等待所有处理异步的最佳方法是什么?

upd:在这里我描述要解决的任务,也许有人会建议在异步中实现它的另一种方法:

我正在实现跨平台IPC流,该流类似于命名管道,但以简化的方式。它应该是完全异步并支持取消的。它应该支持MacOS和Windows上的单声道,因为服务器应用程序依赖于单声道,并且在Windows上不能使用.NET。问题是:Windows上的单声道根本不支持Unix域插座,而命名的管道实现尚未完成(命名的管道连接无法在Mono Windows上取消(。我在Unix域插座上实现了MacOS部分,并且效果很好。在Windows上,我决定基于内存映射文件实现自己的流类。它具有两个共享的读取式缓冲区,用于双工数据交换。每个由命名信号量保护的缓冲区,并有两个命名Event eventwaithandle,一个信号表明缓冲区不是空的,另一个表示缓冲区不满。因此,发送方法等待信号量和非填充事件,以填充缓冲区的数据和信号非空事件,如果实现缓冲区,则它将重置非填充事件。请阅读等待信号和非空的事件,以消耗数据并发出非填充事件,如果它消耗了它重置非空事件的所有数据。它以同步方式完美工作。但是实施可取消的readasync和writeasync。

这有效,但感觉有点脏。这个想法是有效地等待任何一个手柄完成,包括取消令牌的句柄。如果其中一个手柄(取消令牌除外(完成了,请将其从剩余的手柄列表中删除,并有效地等待,直到所有手柄都完成或取消令牌等待手柄已完成。

static async Task<bool> WaitForHandlesAsync(WaitHandle[] handles, CancellationToken cancellationToken) {
    List<WaitHandle> remainingHandles = new List<WaitHandle>(handles.Length + 1);
    remainingHandles.Add(cancellationToken.WaitHandle);
    remainingHandles.AddRange(handles);
    bool canceled = cancellationToken.IsCancellationRequested;
    while (remainingHandles.Count > 1 && !canceled) {
        int idx = await Task.Factory.StartNew(() => WaitHandle.WaitAny(remainingHandles.ToArray()));
        if (idx == 0)
            canceled = true;
        else {
            remainingHandles.RemoveAt(idx);
        }
    }
    return !canceled;
}

最新更新