使用Parallel.For时的限制

时间:2010-07-13 18:17:56

标签: c# parallel-processing throttling

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

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

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

   // Code here

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

2 个答案:

答案 0 :(得分:4)

使用AutoResetEvent和计时器。每当计时器触发时,请将其Set设置为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();
    }

答案 1 :(得分:2)

您可以考虑使用共享ConcurrentQueue,您的并行循环将填充准备好的消息。使用System.Threading.Timer以所需的时间间隔从队列中提取邮件并发送它们。请注意,这种设计只有在创建要发送的消息时才有意义;如果实际发送的消息是昂贵的部分,则没有理由并行运行循环。

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