[英]Does it make sense to call only one `async` method and `await` for it in another `async` method?
[英]Async/Await while another method does the action
我想實現一個流程,其中在類中調用異步方法時,它們將注冊到調度程序列表並等待。 然后,另一個線程從調度程序列表中運行並執行方法,並且當每個操作完成時,等待將完成,我將返回計算出的值。
到目前為止,這是我的代碼:
private List<Func<ClassA, ClassB, ResponseBase>> _actionsDict;
public ExecutingScheduler()
{
_actionsDict = new List<Func<ClassA, ClassB, ResponseBase>>();
Task.Factory.StartNew(ExecuteNextTask);
}
private void ExecuteNextTask()
{
while (_actionsDict.Count > 0)
{
// Get first while removing it
var next = _actionsDict[0];
_actionsDict.RemoveAt(0);
// Next line has an error now, how do I call it with the original params as I added it to the list
next();
Task.Delay(2000);
}
}
public async Task<ResponseBase> StartStreamAsync(ClassA classA, ClassB classB)
{
_actionsDict.Add((unit, guid) => StartStream(classA, classB));
// I don't want the first each time, I want to await the same instance as I added
var response = await Task.Run(() => _actionsDict[0](classA, classB));
return response;
}
public async Task<ResponseBase> PrepareStreamAsync(ClassA classA, ClassB classB)
{
_actionsDict.Add((unit, guid) => PrepareStream(classA, classB));
// I don't want the first each time, I want to await the same instance as I added
var response = await Task.Run(() => _actionsDict[0](classA, classB));
return response;
}
有兩個問題:1)我如何正確地添加到動作列表中,以便以后可以使用其參數依次從列表中調用函數?
2)如何正確地從該執行程序方法的返回值傳遞給原始請求的調用者?
隨時提出不同的方法
我不太明白你的問題。 但是我假設您需要一個帶有兩個async
方法的類,這些方法將按actionDict
的順序進行actionDict
。
無論如何,這是代碼:( 新版本)
List<Task<ResponseBase>> _actionsDict = new List<Task<ResponseBase>>();
Timer _timer = new Timer(1000);
public ExecutingScheduler()
{
_timer.Elapsed += (s, e) => {
while (_actionsDict.Count > 0) {
var a = _actionsDict[0];
_actionsDict.RemoveAt(0);
a.Start();
a.Wait();
}
};
_timer.Start();
}
public Task<ResponseBase> StartStreamAsync(ClassA classA, ClassB classB)
{
return QueueResponse(() => StartStream(classA, classB));
}
public Task<ResponseBase> PrepareStreamAsync(ClassA classA, ClassB classB)
{
return QueueResponse(() => PrepareStream(classA, classB));
}
public Task<ResponseBase> QueueResponse(Func<ResponseBase> action)
{
var t = new Task<ResponseBase>(action);
_actionsDict.Add(t);
return Task.Run(() => t.Result);
}
(已編輯)可以向集合添加任務,而不是向動作集合添加功能。
//Better use thread-safe ConcurrentQueue
private ConcurrentQueue<Task<ResponseBase>> _actions;
public ExecutingScheduler()
{
_actions = new ConcurrentQueue<Task<ResponseBase>>();
Task.Factory.StartNew(ExecuteNextTask);
}
private void ExecuteNextTask()
{
while (true)
{
// Get first while removing it
Task<ResponseBase> next;
var containsElement = _actions.TryDequeue(out next);
if (containsElement)
{
next.Start();
next.Wait();
}
Task.Delay(2000);
}
}
public async Task<ResponseBase> StartStreamAsync(ClassA classA, ClassB classB)
{
var task = new Task<ResponseBase>(() => StartStream(classA, classB));
//Add task to queue
_actions.Enqueue(task);
var result = await task;
return result;
}
public async Task<ResponseBase> PrepareStreamAsync(ClassA classA, ClassB classB)
{
var task = new Task<ResponseBase>(() => PrepareStream(classA, classB));
//Add task to queue
_actions.Enqueue(task);
var result = await task;
return result;
}
看來您正在嘗試重新實現任務並行庫。 特別是TaskScheduler
和Task.WhenAll
。
試試這個吧。
var queries = new []
{
new { ClassA =..., ClassB = ...},
new { ClassA =..., ClassB = ...},
new { ClassA =..., ClassB = ...},
};
var tasks = queries.Select(item => Task.Run(() => PrepareStream(item.ClassA, item.ClassB);
var results = await Task.WhenAll(tasks);
但是,使用諸如PrepareStream
類的名稱,我懷疑您真的不想使用螺紋線。
僅當受CPU約束或具有特殊(UI)線程(這是受CPU約束的特例)時,才應使用線程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.