我正在使用Task.Run
在BlockingCollection
上启动连续的后台处理作业。它可以工作,但是我认为这不是构造代码的理想方法。
此问题与以下行有关:public async Task ProcessQueue()
。我收到警告:
This async method lacks 'await' operators and will run synchronously.
如果我删除async
,则会出现错误:
'MessageProcessor.ProcessQueue()': not all code paths return a value
这是合理的,因为编译器看不到getConsumingEnumerable
块。我应该使用async
版本还是忽略此警告或以其他方式重组代码?
注意:假设我有100个这样的MessageProcessor
,我认为为它们每个创建一个单独的线程不会有效地利用内存,因此我使用Task.Run
。 / p>
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public class Message
{
public int id { get; set; }
public int value { get; set; }
}
public class MessageProcessor
{
private CancellationToken token;
private BlockingCollection<Message> messageQueue;
private List<Message> processedMessageList;
public MessageProcessor(CancellationToken token)
{
this.token = token;
messageQueue = new BlockingCollection<Message>(new ConcurrentQueue<Message>());
processedMessageList = new List<Message>(10);
}
public void Add(Message m)
{
if (!messageQueue.IsAddingCompleted)
{
messageQueue.Add(m);
}
}
public void CompleteAdding()
{
messageQueue.CompleteAdding();
}
public async Task ProcessQueue()
{
foreach (Message m in messageQueue.GetConsumingEnumerable())
{
Console.WriteLine($"Processing. id: {m.id}, value: {m.value}");
processedMessageList.Add(m);
}
}
}
class Program
{
static void Main(string[] args)
{
Random random = new Random();
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
MessageProcessor messageProcessor = new MessageProcessor(token);
var messageProcessorResult = Task.Run(() => messageProcessor.ProcessQueue());
for (int i = 0; i < 10; i++)
{
Message m = new Message();
m.id = i;
m.value = random.Next(-2, 2);
Console.WriteLine($"Producing. id: {m.id}, value: {m.value}");
messageProcessor.Add(m);
}
messageProcessor.CompleteAdding();
messageProcessorResult.Wait();
}
}
答案 0 :(得分:1)
您需要的是action block。
答案 1 :(得分:0)
删除async
并在ProcessQueue
方法的末尾写以下内容:
return Task.CompletedTask;
通过这种方式,我们解决了not all code paths return a value
错误。