【发布时间】:2020-04-09 05:55:49
【问题描述】:
最近,我需要对异步任务进行排队,并且在此链接中向我介绍了 BlockingCollection Queuing asynchronous task in C# 它有效,我的要求略有变化,需要您的指导。我正在使用 @Stephen Cleary 回答中的 BlockingCollection
这是来自该链接的 BlockingCollection
public sealed class ExecutionQueue
{
//private readonly BlockingCollection<Func<Task>> _queue = new BlockingCollection<Func<Task>>();//commented this
private readonly BlockingCollection<Task> _queue = new BlockingCollection<Task>();
public ExecutionQueue() => Complete = Task.Run(() => ProcessQueueAsync());
public Task Completion { get; }
public void Complete() => _queue.CompleteAdding();
private async Task ProcessQueueAsync()
{
foreach (var value in _queue.GetConsumingEnumerable())
await value();
}
}
//public Task Run(Func<Task> lambda)
public Task Run(<Task> lambda)
{
var tcs = new TaskCompletionSource<object>();
_queue.Add(lamda);
return tcs.Task;
}
- 我需要对常规 void 方法中的某些数据库任务进行排队。我可能无法更改此方法的签名。我该怎么做?
public static ExecutionQueue taskQueue = new ExecutionQueue();
private void SaveValesToDB(...)
{
var item = GetID(...);
...
taskQueue.Run(Task.Run(() =>
{
DBInstance.DBSaveValue1(...); // is it correct to wrap with Task.Run and add to queue? it should be queued and run asynchronously
});
...
}
- 我们打开和关闭从数据库中保存和检索数据。因此,当我们排队一个返回类似 getter 的 DB 调用时,我们希望确保在收到返回值之前我们不会处理其他排队的项目。
private void SaveValesToDB(...)
{
...
taskQueue.Run(Task.Run(() =>
{
DBInstance.DBSaveValue1(...); // is this correct? it should be queued and run asynchronously
});
...
taskQueue.Run(Task.Run(() =>
{
var result1 = DBInstance.DBGetValue2(...); // should be queued and run asynchronously;
LogData(result1);// not a DB call but believe it should be wrapped in here for the result1, correct?
});
/*so in above Task.Run, i want to ensure that until i receive result1
i don't process other items in the queue even
if they are added. how can i do that ?
The main thread should continue. */
...
var result 2 = DBInstance.DBGetValue3(...); // should be queued and run asynchronously
UpdateAdvancedLod(result1 +" "+result2);// here, should i block main thread until i get result1 ?
}
- 如何处理错误?
请指导我。
已编辑:
if using Func<Task> in public Task Run(Func<Task> lambda) then is the below correct?
taskQueue.Run(async () =>
{
await Task.Run(() =>
{
DBInstance.DBSaveValue1(...);//is this correct
});
}
);
【问题讨论】:
-
为什么将
Run方法的签名从public Task Run(Func<Task> lambda)改为public Task Run(Task task)?此更改完全破坏了ExecutionQueue类的预期功能。这个类的重点是安排任务在正确的时刻运行。当你给它一个已经创建的任务时,这个任务已经在运行,ExecutionQueue类就失去了它存在的理由。 -
@TheodorZoulias:好的,我明白你的意思了。在我的用例中,如果不想更改 SaveValesToDB() 的方法签名,我该如何将它们添加到队列中?
标签: c# asynchronous async-await queue blockingcollection