在我的生产者 - 消费者应用程序中,我将BufferBlock定义为添加项目的队列。
public static BufferBlock<AppointmentReminder> m_Queue = new BufferBlock<AppointmentReminder>();
SemaphoreSlim seaphore = new SemaphoreSlim(4);
然后要将项目添加到队列中,我有
private static void Producer()
{
for (int i = 0; i < 5000; i++)
{
AppointmentReminder reminder = new AppointmentReminder();
reminder.UniqueId = Guid.NewGuid();
reminder.CallMethod = "Number";
reminder.sString = "1234567890";
m_Queue.Post(reminder);
}
for (int i = 0; i < 3000; i++)
{
AppointmentReminder reminder = new AppointmentReminder();
reminder.UniqueId = Guid.NewGuid();
reminder.CallMethod = "Letter";
reminder.sString = "abcdefghij";
m_Queue.Post(reminder);
}
for (int i = 0; i < 2000; i++)
{
AppointmentReminder reminder = new AppointmentReminder();
reminder.UniqueId = Guid.NewGuid();
reminder.CallMethod = "Mixed";
reminder.sString = "abcd12345y";
m_Queue.Post(reminder);
}
Console.WriteLine("There are {0} items in the queue.\n", m_Queue.Count);
}
现在我必须处理消费者的一部分。有一种方法RunScript(AppointmentReminder callData)
可以做到这一点。这意味着如果项目可用,我们需要在消费者部分中调用该方法。但是有一个节流限制。最大处理项目随时为4个。
所以我有:
private async static Task Consumer()
{
try
{
while (await m_Queue.OutputAvailableAsync())
{
AppointmentReminder reminder = m_Queue.Receive();
Call d = new Call();
d.RunScript(reminder);
}
}
catch (NullReferenceException ex)
{
Console.WriteLine("NullReferenceException: " + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
对于种族生产者和消费者,
static void Main(string[] args)
{
AliveEvent = new ManualResetEvent(false);
Producer();
var consumer = Consumer();
consumer.Wait();
}
我的问题是我对Task Parallel Library (TPL).不强,如何将限制约束应用于消费者?
编辑:2014年10月3日:
基于svick的解决方案。消费者的代码是:
private async static Task Consumer()
{
try
{
while (await m_Queue.OutputAvailableAsync())
{
var consumerBlock = new ActionBlock<AppointmentReminder>(
remainder => new Call().RunScript(remainder),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 });
m_Queue.LinkTo(
consumerBlock, new DataflowLinkOptions { PropagateCompletion = true });
m_Queue.Complete();
consumerBlock.Completion.Wait();
}
// m_Queue is a static BufferBlock in the original code.
}
答案 0 :(得分:2)
比自己编写消费者更好的选择是创建一个ActionBlock
,它已经支持限制并行性:
var consumerBlock = new ActionBlock<AppointmentReminder>(
remainder => new Call().RunScript(remainder),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 });
然后将其链接到队列:
queue.LinkTo(
consumerBlock, new DataflowLinkOptions { PropagateCompletion = true });
最后,等待它完成:
queue.Complete();
consumerBlock.Completion.Wait();