如何实现线程池的 QueueUserWorkItem 方法的延续?
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何实现线程池的 QueueUserWorkItem 方法的延续?相关的知识,希望对你有一定的参考价值。
咨询区
PedroC88
如果我将 Job 通过 QueueUserWorkItem
方法丢到线程池的话,请问我如何让程序在该 Job 完成后继续执行,我知道可以添加一些逻辑代码来完成此项功能,但我想知道有没有类似 Thread.Join()
或者怎么提取到被赋于 job 的线程 ?
回答区
Alex Aza
你可以使用类似 ManualResetEvent
内核事件去同步,参考下面代码:
private static ManualResetEvent resetEvent = new ManualResetEvent(false);
public static void Main()
ThreadPool.QueueUserWorkItem(arg => DoWork());
resetEvent.WaitOne();
public static void DoWork()
Thread.Sleep(5000);
resetEvent.Set();
如果不想把 event 嵌入到 方法中,可以在 QueueUserWorkItem
委托方法中执行,比如下面这样。
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(
arg =>
DoWork();
resetEvent.Set();
);
resetEvent.WaitOne();
对于批量操作,可以定义一个 List<ManualResetEvent>
。
var events = new List<ManualResetEvent>();
foreach(var job in jobs)
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(
arg =>
DoWork(job);
resetEvent.Set();
);
events.Add(resetEvent);
WaitHandle.WaitAll(events.ToArray());
Brian Gideon
可以用 CountdownEvent
或者 Barrier
来做同步。
Barrier barrier = new Barrier(3);
for(int i = 0; i < 2; i++)
ThreadPool.QueueUserWorkItem(
(state) =>
foo();
barrier.SignalAndWait();
, null);
barrier.SignalAndWait();
/* 或者*/
using (var finished = new CountdownEvent(1))
foreach (var workitem in workitems)
var capture = workitem; // Used to capture the loop variable in the lambda expression.
finished.AddCount(); // Indicate that there is another work item.
ThreadPool.QueueUserWorkItem(
(state) =>
try
ProcessWorkItem(capture);
finally
finished.Signal(); // Signal that the work item is complete.
, null);
finished.Signal(); // Signal that queueing is complete.
finished.Wait(); // Wait for all work items to complete.
点评区
如果一定要在 QueueUserWorkItem
中拦截,最好的方式还是用各种锁比较好,如果在实际开发中,建议还是用 Task
,它具有强大的编排能力。
以上是关于如何实现线程池的 QueueUserWorkItem 方法的延续?的主要内容,如果未能解决你的问题,请参考以下文章