2

问候

我有一个程序可以创建一个类的多个实例,在所有实例上运行相同的长时间运行的 Update 方法并等待完成。我从更新添加到ThreadPool.QueueUserWorkItem.

在主编中,我睡了几分钟,检查最后一个孩子的布尔值,看看是否完成

while(!child[child.Length-1].isFinished) {
    Thread.Sleep(...);
}

这个解决方案正在按照我想要的方式工作,但是有没有更好的方法来做到这一点?对于独立实例和检查所有工作是否已完成。

谢谢

更新: 不需要锁定。不同的实例每个都有不同的 Web 服务 URL,它们从它们请求,并在响应上做类似的工作。他们都在做自己的事情。

4

4 回答 4

1

你可以试试信号量

于 2010-03-31T14:48:55.870 回答
1

阻塞的等待方式比轮询更优雅一些。请参阅Monitor.Wait/ Monitor.PulseSemaphore也可以)以获取阻止和发出信号的简单方法。C# 在 Monitor 类周围有一些以lock关键字形式存在的语法糖。

于 2010-03-31T14:51:36.987 回答
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 框架(和一般的 Windows 操作系统)有许多线程原语,专门设计用于防止需要自旋锁,而轮询循环Sleep实际上只是一个慢速自旋锁。

于 2010-03-31T14:59:25.323 回答
1

这看起来不太好。几乎没有任何正当理由可以假设当最后一个线程完成时,其他线程也完成了。除非您以某种方式联锁工作线程,否则您永远不应该这样做。Sleep() 也没有什么意义,等待线程完成。你不妨做那个线程正在做的工作。

如果您有多个线程正在运行,请为每个线程分配一个 ManualResetEvent。您可以使用 WaitHandle.WaitAll() 等待完成。使用 Interlocked 类倒计时线程计数器也可以工作。或使用 CountdownLatch。

于 2010-03-31T15:18:50.353 回答