繁体   English   中英

等待任何线程完成,而不是全部

[英]Wait for ANY thread to finish, not ALL

我开始多线程和想知道当任何然后完成。 我知道以下代码:

foreach (Thread t in threads)
    t.Join();

但它只会等待所有线程在一起。 那太晚了。 我需要知道一个线程何时完成,即使其他线程仍在运行。 我正在为线程寻找等同于WaitAny东西。 但是我无法将代码添加到我正在监视的所有线程中,因此使用信号或其他同步对象不是一种选择。

一些澄清:我正在开发一个记录/跟踪工具,它应该记录应用程序的活动。 我可以在线程启动时插入日志语句,但是我不能在线程的每个可能的方式上插入日志语句(多个退出点,异常等)。 所以我想注册新线程,然后在完成写入日志条目时收到通知。 我可以异步Join每个线程,但这意味着每个受监控线程的第二个线程可能看起来有点开销。 线程通过各种方式使用,无论是BackgroundWorkerTask还是池线程。 从本质上讲,它是一个线程,我想知道它什么时候完成。 确切的线程机制由应用程序定义,而不是日志记录解决方案。

而不是线程使用任务 它有WaitAny方法。

Task.WaitAny

你可以在这里看到

  • 更高效,更可扩展的系统资源使用。
  • 比线程或工作项更多的程序控制。

在我看来WaitHandle.WaitAny是最好的解决方案,因为你不喜欢用它来解决一些xyz的原因,你可以试试这样的东西。

利用Thread.Join(int)方法,该方法占用millisecond timeout并在线程终止时返回true ,或在超时时返回false

List<Thread> threads = new List<Thread>();

while (!threads.Any(x=> x.Join(100)))
{

}

您可以更改Join的超时如果您知道需要多长时间。

我的回答是基于你的澄清,你所拥有的只是Thread.Current 免责声明:IMO,你要做的就是黑客,所以我的想法无论如何都是黑客攻击

因此,使用反射来获取所需线程的本机Win32句柄集。 您正在寻找internal Thread.GetNativeHandle方法,因此您可以将其thread.GetType().InvokeMember("GetNativeHandle", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic, ...) 使用您选择的反射工具或框架源来了解有关它的更多信息。 获得句柄后,继续使用以下选项之一:

  • 设置自己的SynchronizationContext实现(从中派生)并使用SynchronizationContext.WaitHelper(waitAll:false)等待非托管句柄。

  • 使用原始Win32 API,如WaitForMultipleObjectsCoWaitForMultipleObjects (取决于您是否需要抽取消息)。

在单独的子线程或池线程上执行等待。

[已编辑]根据目标线程的执行环境,此hack可能无法正常工作,因为无法保证托管和非托管线程之间的一对一映射:

可以确定正在执行托管线程代码的Windows线程并检索其句柄。 但是,为此Windows线程调用SetThreadAffinityMask函数仍然没有意义, 因为托管调度程序可以继续在另一个Windows线程中执行托管线程

但是,这似乎只对自定义CLR主机有影响 此外,似乎可以使用Thread.BeginThreadAffinityThread.EndThreadAffinity 控制托管线程关联

您可以使用后台工作程序来处理工作线程。

然后将所有RunWorkerCompleted事件挂钩到将等待它们的方法。

如果您希望将其同步到当前正在等待连接的代码,则问题将减少为仅将该单个事件方法同步到代码中的该位置。

更好的是,我建议你在不阻塞的情况下异步进行你正在做的事情,并在事件中做你想做的事。

你会考虑用另一个“日志记录”线程包装你的线程调用吗? 这样你就可以在线程运行之前和之后同步记录。

像这样的伪代码:

int threadLogger(<parms>) {
    log("starting thread");
    retcode = ActualThreadBody(<parms>);
    log("exiting thread");
    return retcode;
}

如果您有关于已启动线程的更多信息,您也可以记录该信息。 在有多种类型的线程可以启动的情况下,您也可以将线程函数作为参数,这听起来就像您一样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM