Async/Await,而另一个方法执行操作

本文关键字:方法 执行 操作 另一个 Await Async | 更新日期: 2023-09-27 18:08:05

我想实现一个流,当调用类中的异步方法时,它们将注册到调度程序列表并等待。然后另一个线程运行并执行调度程序列表中的方法,当每个操作完成时,await将完成,并且我将返回计算的值。

下面是我的代码:
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/Await,而另一个方法执行操作

我不太明白你的问题。但我假设您需要一个类,其中包含两个async方法,这些方法将按照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);
    }

看起来您正在尝试重新实现任务并行库。特别是TaskSchedulerTask.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限制的特殊情况)时使用。

(EDITED)你可以向集合中添加任务,而不是向集合中添加函数。

//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;
}