C# TAP 异步 多个排队延迟,然后取消排队



我有一个系统,其中使用对象调用方法,并使用具有第一个列表的不同对象编写数据库。

现在:

private async Task SaveAMessage(Messsage message)
{
    var messages = new List<Message>();
    messages.Add(message);
    var envelope = new Envelope();
    envelope.messages = messages;
    await _db.Save(envelope);
}

但我只能每 1 秒跑一次_db.Save

TAP的说法是什么:将此项目添加到列表中,然后在1秒后将它们全部保存在一起。下面我有一些假代码,表达了我希望我能写的东西

Javascript-y 伪代码:

private List<Message> messages = new List<Message>();
private int? valueCheckTimer;
private async Task SaveAMessage(Messsage message)
{
    messages.Add(message);
    if (valueCheckTimer) { 
        return;
    }
    valueCheckTimer = setTimeout(function () {
        var envelope = new Envelope();
        envelope.messages = messages;
        await _db.Save(envelope);
        messages.Clear();
    },1000);
}

如何编写与伪代码的工作方式相同的 C# 代码?

实际上,您只需进行一个非常简单的小更改即可做到这一点。 向SaveAMessage添加一个WhenAll以等待Save以及对Task.Delay的调用:

private async Task SaveAMessage(Messsage message)
{
    var messages = new List<Message>();
    messages.Add(message);
    var envelope = new Envelope();
    envelope.messages = messages;
    await Task.WhenAll(_db.Save(envelope), Task.Delay(1000));
}

现在,您可以遍历所有对SaveAMessage的调用,等待所有调用,并且可以确保它等到上一次保存完成,并且至少经过一秒钟后才能继续。

如果您在其他地方使用SaveAMessage有时不需要等待整整一秒钟,那么只需拉出此更改,并让您用于保存所有消息的任何代码等待Task.Dealy调用。

试试这段 c# 代码(以 ConsoleApp 身份运行):

namespace ConsoleApplication1
{
    public class Program
    {
        private static async Task<string> SaveAMessage(string message)
        {
            var messages = new List<string>();
            messages.Add(message);
            return await save(messages);
        }
        private static Task<string> save(List<string> msg)
        {
            Task<string> task = Task.Factory.StartNew<string>(() =>
            {
                Console.WriteLine("Message " + msg[0] + " received...");
                Console.WriteLine("Message " + msg[0] + " running...");
                Thread.Sleep(3000);
                return "Message " + msg[0] + " finally return.";
            });
            return task;
        }
        public static void Main(string[] args)
        {
            Task<string> first = SaveAMessage("Msg1");
            first.ContinueWith(x => Console.WriteLine("Print " + x.Result));
            Task<string> second = SaveAMessage("Msg2");
            second.ContinueWith(x => Console.WriteLine("Print " + x.Result));
            Task<string> third = SaveAMessage("Msg3");
            third.ContinueWith(x => Console.WriteLine("Print " + x.Result));
            Task<string> fourth = SaveAMessage("Msg4");
            fourth.ContinueWith(x => Console.WriteLine("Print " + x.Result));
            Task<string> fifth = SaveAMessage("Msg5");
            fifth.ContinueWith(x => Console.WriteLine("Print " + x.Result));
            Console.ReadKey();
        }    
    }
}

最新更新