当使用单线程循环时,我很容易通过将线程置于休眠状态(即Thread.Sleep(1000/MessagesPerSecond)
)来限制每秒发送的消息,这很容易......但是现在我已经扩展为并行线程这不再正常。
有没有人建议如何限制使用并行线程时发送的消息?
Parallel.For(0, NumberOfMessages, delegate(int i) {
// Code here
if (MessagesPerSecond != 0)
Thread.Sleep(1000/MessagesPerSecond);
});
答案 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。