[英]Async/Await while another method does the action
I want to implement a flow in which when calling async methods in my class, they would sign up to a scheduler list and wait. 我想实现一个流程,其中在类中调用异步方法时,它们将注册到调度程序列表并等待。 Then another thread running and executing methods from the scheduler list, and when each action is finished, the await will finish and I will return the value that was calculated. 然后,另一个线程从调度程序列表中运行并执行方法,并且当每个操作完成时,等待将完成,我将返回计算出的值。
Here is my code so far: 到目前为止,这是我的代码:
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;
}
So two questions: 1) How do I properly add to the list of actions so I can later call functions from the list one after one with their params? 有两个问题:1)我如何正确地添加到动作列表中,以便以后可以使用其参数依次从列表中调用函数?
2) How do I properly pass the return value from that executer method to the caller of the original request? 2)如何正确地从该执行程序方法的返回值传递给原始请求的调用者?
feel free to suggest a different approach 随时提出不同的方法
I don't quite get your question. 我不太明白你的问题。 But I assume that you need a class with two async
methods that would do things as the order in the actionDict
. 但是我假设您需要一个带有两个async
方法的类,这些方法将按actionDict
的顺序进行actionDict
。
Anyway, here's the code: (New Version) 无论如何,这是代码:( 新版本)
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);
}
(EDITED) Instead of adding functions to actions collection you could add task to collection. (已编辑)可以向集合添加任务,而不是向动作集合添加功能。
//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;
}
It looks like you are trying to reimplement the Task Parallel Library. 看来您正在尝试重新实现任务并行库。 Specifically TaskScheduler
and Task.WhenAll
. 特别是TaskScheduler
和Task.WhenAll
。
Try this instead. 试试这个吧。
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);
However with a name like PrepareStream
I suspect you REALLY DON'T WANT TO USE A THREAD. 但是,使用诸如PrepareStream
类的名称,我怀疑您真的不想使用螺纹线。
Threading should ONLY BE USED when you are CPU bound or you have a special (UI) thread (which is a special case of CPU bound). 仅当受CPU约束或具有特殊(UI)线程(这是受CPU约束的特例)时,才应使用线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.