繁体   English   中英

使用Task.Run通过BlockingCollection启动连续运行的后台作业

[英]Using Task.Run to start a continuously running background job with a BlockingCollection

我正在使用Task.RunBlockingCollection上启动连续的后台处理作业。 它可以工作,但我认为这不是构造代码的理想方法。

此问题与以下代码有关: 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


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();
    }
}

您需要的是一个动作块

删除async并在ProcessQueue方法的末尾编写以下内容:

return Task.CompletedTask;

这样,我们解决了not all code paths return a value错误的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM