簡體   English   中英

當另一種方法執行操作時異步/等待

[英]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;
}

看來您正在嘗試重新實現任務並行庫。 特別是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約束的特例)時,才應使用線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM