Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 等待任何线程完成,而不是所有线程_C#_Multithreading_Synchronization - Fatal编程技术网

C# 等待任何线程完成,而不是所有线程

C# 等待任何线程完成,而不是所有线程,c#,multithreading,synchronization,C#,Multithreading,Synchronization,我正在启动多个线程,希望知道其中任何线程何时完成。我知道以下代码: foreach (Thread t in threads) t.Join(); 但它只会同时等待所有线程。那太晚了。我需要知道一个线程何时结束,即使其他线程仍在运行。我正在寻找仅针对线程的等价于WaitAny。但是我不能向我监视的所有线程添加代码,所以使用信号或其他同步对象不是一个选项 一些澄清:我正在开发一个日志/跟踪工具,它应该记录应用程序的活动。我可以在线程启动时插入日志语句,但我不能在线程之外的每一条可能的路径

我正在启动多个线程,希望知道其中任何线程何时完成。我知道以下代码:

foreach (Thread t in threads)
    t.Join();
但它只会同时等待所有线程。那太晚了。我需要知道一个线程何时结束,即使其他线程仍在运行。我正在寻找仅针对线程的等价于
WaitAny
。但是我不能向我监视的所有线程添加代码,所以使用信号或其他同步对象不是一个选项


一些澄清:我正在开发一个日志/跟踪工具,它应该记录应用程序的活动。我可以在线程启动时插入日志语句,但我不能在线程之外的每一条可能的路径上插入日志语句(多个退出点、异常等)。因此,我希望注册新线程,然后在它完成写入日志条目时收到通知。我可以在每个线程上异步地
连接
,但这意味着每个受监视的线程都有一个第二个线程,这可能会有点大的开销。线程的使用方式多种多样,可以是
BackgroundWorker
Task
或池线程。本质上,它是一根线,我想知道它什么时候完成。确切的线程机制是由应用程序定义的,而不是日志解决方案。

在我看来
WaitHandle.WaitAny
是最好的解决方案,因为出于某些xyz原因,您不喜欢使用它,您可以尝试类似的方法

利用这种方法,当线程终止或超时时,该方法采用
毫秒超时
并返回
true

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

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

}
List threads=newlist();
而(!threads.Any(x=>x.Join(100)))
{
}
如果您知道需要多长时间,您可以更改加入的超时时间。

您可以使用工作线程的工作线程

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

如果希望将其同步到当前正在等待连接的代码中,那么问题将简化为仅将该单事件方法同步到代码中的该位置

更好的是,我建议您在不阻塞的情况下异步执行您正在执行的操作,并在事件中执行您想要的操作

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

正如你所看到的

  • 更高效、更可扩展地使用系统资源
  • 比线程或工作项可能实现的编程控制更多

我的回答是基于您的澄清,即您所拥有的是
线程。当前
免责声明:在我看来,你试图做的是一种黑客行为,因此我的想法当然也是一种黑客行为

因此,使用反射来获取所需线程的本机Win32句柄集。您正在寻找
Thread.GetNativeHandle
方法,该方法是
内部的
,因此您可以像
Thread.GetType().InvokeMember(“GetNativeHandle”,BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic,…)
。使用您选择的反射工具或了解更多信息。获得手柄后,继续使用以下选项之一:

  • 设置自己的
    SynchronizationContext
    (从中派生)实现,并使用等待非托管句柄

  • 使用原始Win32 API,如
    WaitForMultipleObjects
    CoWaitForMultipleObjects
    (取决于是否需要发送消息)

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

[已编辑]根据目标线程的执行环境,此攻击可能不起作用,因为托管线程和非托管线程之间的一对一映射:

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


但是,这可能仅适用于自定义CLR主机。此外,似乎还可以使用
Thread.BeginThreadAffinity
Thread.EndThreadAffinity

> P>你会考虑用另一个“日志”线程来包装线程调用吗?这样,您就可以在线程运行之前和之后同步地进行日志记录

类似于以下伪代码:

int threadLogger(<parms>) {
    log("starting thread");
    retcode = ActualThreadBody(<parms>);
    log("exiting thread");
    return retcode;
}
int线程记录器(){
日志(“起始线程”);
retcode=ActualThreadBody();
日志(“退出线程”);
返回代码;
}
如果您有关于启动线程的更多信息,也可以将其记录下来。
在有多种类型的线程要启动的情况下,您也可以将thread函数作为参数,这听起来像是一种代码味道。你们不知道哪个线程完成了,所以你们不能解释到底完成了什么工作。我已经添加了更多关于我要做什么的背景知识。当然,我需要知道哪个线程已经完成,否则在这种情况下它将是无用的。我和汉斯在这一个。为什么线程代码有多个退出点?在所有线程代码中设置一个尝试/捕获,如果你想退出中间的某个位置,就抛出。我所有的其他疑问都被现有的答案所掩盖了——为什么你不断地创建/终止/销毁线程,而不是使用刚刚收到信号的池或应用程序生命周期线程?同样,我不能控制应用程序对线程的操作。我的目标只是提供一个日志记录解决方案,它将在线程完成时写入日志条目。如果我能完全控制要记录的内容,那么,当然,我可以按照你的建议去做。我想这会被提议的(忘了提及)。我只是担心监视线程w上的持续活动
int threadLogger(<parms>) {
    log("starting thread");
    retcode = ActualThreadBody(<parms>);
    log("exiting thread");
    return retcode;
}