我试图让我的头脑围绕下面的设计,但没有得到一个清晰的画面。
我有许多生产者将任务/作业提交到队列中。然后,消费者/工人就会捡起这些,并完成这些工作。目前,只有一个消费者/工人。
到目前为止,这听起来像标准的生产者/消费者模式,可以用BlockingCollection来完成。
但是,一些生产者可能希望提交任务/作业,并且能够等待任务/作业的完成(或者提交多个任务/作业,等待部分或全部任务/作业等等),而其他生产者则只是“触发和忘记”他们的任务/作业。(请注意,这不是等待队列为空,而是等待特定的任务/作业)。
这是怎么做的?在我看到的所有例子中,生产者只是使用BlockingQueue.Add()将数据发布到队列中。
任何帮助都将不胜感激。
发布于 2018-03-28 19:52:46
一种常见的方法是使用一个TaskCompletionSource包装您的工作操作,它的Task可以返回给调用者并等待完成。
public class ProducerConsumerQueue
{
private readonly BlockingCollection<Action> queue = new BlockingCollection<Action>();
public Task Produce(Action work)
{
var tcs = new TaskCompletionSource<bool>();
Action action = () =>
{
try
{
work();
tcs.SetResult(true);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
};
queue.Add(action);
return tcs.Task;
}
public void RunConsumer(CancellationToken token)
{
while (true)
{
token.ThrowIfCancellationRequested();
var action = queue.Take(token);
action();
}
}
}也就是说,您应该考虑利用TPL本身提供的任务基础结构,而不是自己的结构。如果您的唯一需求是有一定数量的消费者,则可以使用LimitedConcurrencyLevelTaskScheduler。
https://stackoverflow.com/questions/49537680
复制相似问题