我有一个系统,其中使用对象调用方法,并使用具有第一个列表的不同对象编写数据库。
现在:
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();
}
}
}