C# 对“即发即弃”的改进

发布于 2024-08-26 21:50:41 字数 553 浏览 5 评论 0原文

我有一个程序

,它创建一个类的多个实例,在所有实例上运行相同的长时间运行的 Update 方法并等待完成。我正在遵循这个问题<的Kev方法< /a> 将更新添加到 ThreadPool.QueueUserWorkItem。

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

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

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

谢谢

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

Greetings

I have a program that creates multiples instances of a class, runs the same long-running Update method on all instances and waits for completion. I'm following Kev's approach from this question of adding the Update to ThreadPool.QueueUserWorkItem.

In the main prog., I'm sleeping for a few minutes and checking a Boolean in the last child to see if done

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

This solution is working the way I want, but is there a better way to do this? Both for the independent instances and checking if all work is done.

Thanks

UPDATE:
There doesn't need to be locking. The different instances each have a different web service url they request from, and do similar work on the response. They're all doing their own thing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

面犯桃花 2024-09-02 21:50:41

如果您知道将执行的操作数,请使用倒计时和事件:

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 的轮询循环实际上只是慢速自旋锁。

If you know the number of operations that will be performed, use a countdown and an event:

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();
}

Don't poll for completion. The .NET Framework (and the Windows OS in general) has a number of threading primitives specifically designed to prevent the need for spinlocks, and a polling loop with Sleep is really just a slow spinlock.

黑寡妇 2024-09-02 21:50:41

您可以尝试信号量

You can try Semaphore.

季末如歌 2024-09-02 21:50:41

阻塞等待方式比轮询更优雅一点。请参阅 Monitor.Wait/Monitor.PulseSemaphore 也可以正常工作),了解阻塞和发出信号的简单方法。 C# 以 lock 关键字的形式围绕 Monitor 类提供了一些语法糖。

A blocking way of waiting is a bit more elegant than polling. See the Monitor.Wait/Monitor.Pulse (Semaphore works ok too) for a simple way to block and signal. C# has some syntactic sugar around the Monitor class in the form of the lock keyword.

始于初秋 2024-09-02 21:50:41

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

如果您有多个线程运行,请为每个线程提供一个 ManualResetEvent。您可以使用 WaitHandle.WaitAll() 等待完成。使用 Interlocked 类对线程计数器进行倒计时也可以。或者使用 CountdownLatch。

This doesn't look good. There is almost never a valid reason to assume that when the last thread is completed that the other ones are done as well. Unless you somehow interlock the worker threads, which you should never do. It also makes little sense to Sleep(), waiting for a thread to complete. You might as well do the work that thread is doing.

If you've got multiple threads going, give them each a ManualResetEvent. You can wait on completion with WaitHandle.WaitAll(). Counting down a thread counter with the Interlocked class can work too. Or use a CountdownLatch.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文