3

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

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

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

   // Code here

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

2 回答 2

4

使用 AutoResetEvent 和计时器。每当计时器触发时,让它Set发生 AutoResetEvent。

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

    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();
    }
于 2010-07-13T18:23:15.953 回答
2

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

如果您需要在发送消息后停止计时器,则必须做一些额外的工作,但这种设计对于必须处理异步消息队列的受限制的消息发送者来说效果很好。另一个需要考虑的边界情况是“消息堆积”,即消息排队的速度超过了处理速度。在这种情况下,您可能需要考虑生成错误(因为它可能表明存在错误)或使用BlockingCollection

于 2010-07-13T19:14:14.853 回答