[英]C# Improvement on a Fire-and-Forget
问候
我有一个程序,该程序创建一个类的多个实例,在所有实例上运行相同的长时间运行的Update方法,并等待完成。 我正在从将Update添加到ThreadPool.QueueUserWorkItem
问题中遵循Kev的方法。
在主程序中,我睡了几分钟,检查最后一个孩子中的布尔值,看是否完成
while(!child[child.Length-1].isFinished) {
Thread.Sleep(...);
}
该解决方案可以按我想要的方式工作,但是有更好的方法吗? 对于独立实例和检查是否所有工作都已完成。
谢谢
更新:不需要锁定。 每个不同的实例都有各自请求的不同Web服务URL,并对响应进行类似的工作。 他们都在做自己的事。
您可以尝试Semaphore 。
阻塞的等待方式比轮询更优雅。 有关阻塞和发出信号的简单方法,请参见Monitor.Wait
/ Monitor.Pulse
( Semaphore
也可以)。 C#在Monitor类周围有一些语法糖,形式为lock
关键字。
如果您知道将要执行的操作数,请使用倒计时和事件:
Activity[] activities = GetActivities();
int remaining = activities.Length;
using (ManualResetEvent finishedEvent = new ManualResetEvent(false))
{
foreach (Activity activity in activities)
{
ThreadPool.QueueUserWorkItem(s =>
{
activity.Run();
if (Interlocked.Decrement(ref remaining) == 0)
finishedEvent.Set();
});
}
finishedEvent.WaitOne();
}
不要轮询完成。 .NET Framework(和通常的Windows OS)具有许多专门设计用于防止需要自旋锁的线程原语,而使用Sleep
的轮询循环实际上只是一个缓慢的自旋锁。
这看起来不太好。 几乎没有绝对的理由认为,当最后一个线程完成时,其他线程也将完成。 除非您以某种方式将工作线程互锁,否则永远不要这样做。 对于等待线程完成的Sleep()也没有什么意义。 您也可以执行线程正在执行的工作。
如果您有多个线程,请给每个线程一个ManualResetEvent。 您可以使用WaitHandle.WaitAll()等待完成。 用Interlocked类对线程计数器进行计数也可以工作。 或使用CountdownLatch。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.