C#改进了Fire-For-Forget

时间:2010-03-31 14:46:05

标签: c# optimization fire-and-forget

问候

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

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

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

这个解决方案按照我想要的方式工作,但是有更好的方法吗?两者都用于独立实例并检查是否所有工作都已完成。

由于

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

4 个答案:

答案 0 :(得分:1)

您可以尝试Semaphore

答案 1 :(得分:1)

阻止等待的方式比轮询更优雅。有关阻止和发送信号的简单方法,请参阅Monitor.Wait / Monitor.PulseSemaphore也可以正常工作)。 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。