gpt4 book ai didi

C# 线程,WaitHandle.WaitAll

转载 作者:行者123 更新时间:2023-11-30 22:42:47 33 4
gpt4 key购买 nike

是否有可能不使用 WaitHandle.WaitAll(waitHandles) 阻止 winForm,而是设置另一个线程,当从 WaitHandle.WaitAll 获取完成信号时将触发该线程?

最佳答案

我不会使用 WaitHandle.WaitAll。这种方法有几个问题。

  • 有 64 个句柄限制。
  • 它不能用于 STA 线程。
  • 它提倡依赖于创建明显消耗资源的多个 WaitHandle 实例的模式。

相反,当我想等待多个事件时,我通常使用 CountdownEvent 类。现在,您将遇到的问题是它仍然需要您在某个线程上调用 Wait,这正是您要避免的。避免进行阻塞调用的标准机制是使用 ThreadPool.RegisterWaitForSingleObject 方法。但是,不幸的是,它需要一个 WaitHandle 并且 CountdownEvent 没有从那个类继承。

解决方案是创建您自己的 CountdownWaitHandle 类,该类可在 ThreadPool.RegisterWaitForSingleObject 方法中使用。这种方法将允许您指定一个回调委托(delegate),该委托(delegate)将在 WaitHandle 发出信号后执行。

这是 CountdownWaitHandle 类最基本的实现。您必须自己添加所有必要的硬编码,但这将帮助您入门。

public class CountdownWaitHandle : WaitHandle
{
private int m_Count = 0;
private ManualResetEvent m_Event = new ManualResetEvent(false);

public CountdownWaitHandle(int initialCount)
{
m_Count = initialCount;
}

public void AddCount()
{
Interlocked.Increment(ref m_Count);
}

public void Signal()
{
if (Interlocked.Decrement(ref m_Count) == 0)
{
m_Event.Set();
}
}

public override bool WaitOne()
{
return m_Event.WaitOne();
}
}

这里的想法是不要使用许多不同的 WaitHandle 实例,而是使用单个 CountdownWaitHandle 实例。使用所需的计数初始化实例,然后调用 Signal 来减少计数。一旦计数变为零,WaitHandle 将进入信号状态。因此,不是在多个 WaitHandle 实例上调用 Set 并使用 WaitHandle.WaitAll 进行阻塞,而是在这个实例上调用 Signal通过调用 WaitOne 实例和 block 。同样,您可以使用 TheadPool.RegisterWaitForSingleObject 推迟对线程池的阻塞调用,这将在 WaitHandle 发出信号时调用回调。

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

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