使用 Parallel.For 时的限制

发布于 2024-09-10 02:01:33 字数 323 浏览 3 评论 0原文

当使用单线程循环时,我可以轻松地通过将线程置于睡眠状态(即 Thread.Sleep(1000/MessagesPerSecond))来限制每秒发送的消息,这很容易......但现在我已经扩展到并行线程,这不再正常工作。

有人建议如何限制使用并行线程时发送的消息吗?

Parallel.For(0, NumberOfMessages, delegate(int i) {

   // Code here

   if (MessagesPerSecond != 0)
      Thread.Sleep(1000/MessagesPerSecond);
});

When using a single threaded loop, I was easily able to limit my messages sent per second by putting the thread to sleep (i.e. Thread.Sleep(1000/MessagesPerSecond)), easy enough... but now that I have expanded into parallel threads this no longer works correctly.

Does anyone have a suggestion how to throttle messages sent when using Parallel threads?

Parallel.For(0, NumberOfMessages, delegate(int i) {

   // Code here

   if (MessagesPerSecond != 0)
      Thread.Sleep(1000/MessagesPerSecond);
});

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

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

发布评论

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

评论(2

旧时模样 2024-09-17 02:01:33

使用 AutoResetEvent 和计时器。每当计时器触发时,就让它设置 AutoResetEvent。

然后让您的进程在发送之前立即在 AutoResetEvent 上发送消息 WaitOne

    private static readonly AutoResetEvent _Next = new AutoResetEvent(true);
    private static Timer _NextTimer;

    private static void SendMessages(IEnumerable<Message> messages)
    {
        if (_NextTimer == null)
            InitializeTimer();

        Parallel.ForEach(
            messages,
            m =>
            {
                _Next.WaitOne();
                // Do something
            }
            );
    }

    private static void SetNext(object state)
    {
        _Next.Set();
    }

Use an AutoResetEvent and a timer. Whenever the timer fires, have it Set the AutoResetEvent.

Then have your process that sends messages WaitOne on the AutoResetEvent immediately before sending.

    private static readonly AutoResetEvent _Next = new AutoResetEvent(true);
    private static Timer _NextTimer;

    private static void SendMessages(IEnumerable<Message> messages)
    {
        if (_NextTimer == null)
            InitializeTimer();

        Parallel.ForEach(
            messages,
            m =>
            {
                _Next.WaitOne();
                // Do something
            }
            );
    }

    private static void SetNext(object state)
    {
        _Next.Set();
    }
舞袖。长 2024-09-17 02:01:33

您可以考虑使用共享的 ConcurrentQueue,您的并行循环将填充它与准备好的消息。使用 System.Threading.Timer 拉取消息按照您想要的时间间隔从队列中取出并发送它们。请注意,只有当创建要发送的消息成本很高时,这种设计才有意义。如果消息的实际发送是昂贵的部分,则没有理由并行运行循环。

如果您需要在发送消息后停止计时器,则必须执行一些额外的工作,但这种设计非常适合必须处理异步消息队列的受限制的消息发送方。另一个需要考虑的边界情况是“消息堆积”,即消息排队的速度比处理消息的速度快。您可能需要考虑在这种情况下生成错误(因为它可能表示错误)或使用 阻止集合

You might consider using a shared ConcurrentQueue, which your parallel loop would populate with prepared messages. Use the System.Threading.Timer to pull messages from the queue at your desired interval and send them. Note that this design only make sense if creating the messages to be sent is expensive; if the actual sending of the messages is the expensive part, there is no reason to run the loop in parallel.

If you need to stop the timer after the messages have been sent, you'll have to do some additional work, but this design works well for a throttled message sender that has to handle asynchronous message queuing. Another boundary case to consider is 'message pile-up', where messages are queued up faster than they can be processed. You might want to consider generating an error in this case (as it may indicate a bug) or using a BlockingCollection.

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