问候
我有一个程序可以创建一个类的多个实例,在所有实例上运行相同的长时间运行的Update方法并等待完成。我正在跟踪Kev从this question添加更新到ThreadPool.QueueUserWorkItem
的方法。
在主编程中,我正在睡觉几分钟并检查最后一个孩子的布尔值,看看是否已完成
while(!child[child.Length-1].isFinished) {
Thread.Sleep(...);
}
这个解决方案按照我想要的方式工作,但是有更好的方法吗?两者都用于独立实例并检查是否所有工作都已完成。
由于
更新 不需要锁定。每个不同的实例都有一个他们请求的不同Web服务URL,并对响应做类似的工作。他们都在做自己的事情。
答案 0 :(得分:1)
您可以尝试Semaphore。
答案 1 :(得分:1)
阻止等待的方式比轮询更优雅。有关阻止和发送信号的简单方法,请参阅Monitor.Wait
/ Monitor.Pulse
(Semaphore
也可以正常工作)。 C#在Monitor类中以lock
关键字的形式存在一些语法糖。
答案 2 :(得分:1)
如果您知道将要执行的操作数,请使用倒计时和事件:
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操作系统)有许多专门用于防止需要自旋锁的线程原语,而Sleep
的轮询循环实际上只是一个缓慢的自旋锁
答案 3 :(得分:1)
这看起来不太好。几乎没有一个合理的理由可以假设当最后一个线程完成时,其他线程也完成了。除非你以某种方式联系工作线程,否则你永远不应该这样做。 Sleep()也没什么意义,等待线程完成。你也可以做一下线程正在做的工作。
如果你有多个线程,请给每个线程一个ManualResetEvent。您可以使用WaitHandle.WaitAll()等待完成。使用Interlocked类计算线程计数器也可以工作。或者使用CountdownLatch。