繁体   English   中英

一劳永逸的C#改进

[英]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.PulseSemaphore也可以)。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM