簡體   English   中英

異步/等待 - 等待沒有按預期保持

[英]Async/Await - Await not holding as expected

在執行長時間運行的操作時,我注意到我可以在啟動行之前啟動長時間運行的子操作,並在從緩存/數據庫中獲取結果時執行其他操作。

給定的操作是:

public async Task<Fichaclis> Finalize()
{
     using (TransactionScope transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
     {
         transactionTimer.Start();
         var agendasTransitionTask = ExecuteAgendas();

                ... DO ALOT OF SYNC OPERATIONS ...
         await agendasTransitionTask;
         transaction.Complete();
     }
}
private Task ExecuteAgendas()
{
    return ags.GetAgendas().ContinueWith((prev) =>
    {
        var currentAgendas = prev.Result;
        foreach (var item in currentAgendas)
        {
            ... DO QUICK SYNC STUFF...
        }
        return ags.BulkEditAgenda(currentAgendas);
    });
}

GetAgendas是一個使用以下簽名的方法:
public async Task<List<Agendas>> GetAgendas()
因為它被廣泛使用,我相信問題不存在。 至於BulkEditAgenda

public async Task BulkEditAgenda(IEnumerable<Agendas> agendas)
{
    if (agendas == null || agendas.Count() == 0)
    {
        return;
    }
    var t1 = AddOrUpdateCache(agendas);
    var t2 = Task.Factory.StartNew(() =>
    {
        try
        {
            foreach (var item in agendas)
            {
                EditNoReconnection(item);
            }
            Save();
        }
        catch (Exception ex)
        {
            //log
            throw;
        }
    });
    await Task.WhenAll(t1, t2);
}

EditNoReconnectSave都是同步方法。

private Task AddOrUpdateCache(IEnumerable<Agendas> agendas)
{
    var tasks = new List<Task>();
    foreach (var item in agendas)
    {
        tasks.Add(TryGetCache(item)
            .ContinueWith((taskResult) =>
            {
                ...DO QUICK SYNC STUFF...
            })
        );
    }
    return Task.WhenAll(tasks);
}

TryGetCache也是一種廣泛使用的方法,所以我認為它是安全的......它的簽名是private Task<AgendasCacheLookupResult> TryGetCache(

因此,恢復手頭的問題:對於在Finalize方法的同步會話中執行的一小組項目,命令transaction.Complete()Save()之前執行(在BulkEditAgendas內)。 對於常規或大量的項目,它按預期工作。
這意味着我沒有正確地鏈接Tasks ,或者我對Async / Await + Tasks / ContinueWith如何工作的理解從根本上說是不正確的。 我哪里錯了?

問題最有可能在這里:

private Task ExecuteAgendas()
{
    return ags.GetAgendas().ContinueWith((prev) =>
    {
        var currentAgendas = prev.Result;
        foreach (var item in currentAgendas)
        {
            ... DO QUICK SYNC STUFF...
        }
        return ags.BulkEditAgenda(currentAgendas);
    });
}

首先,你從中返回的是繼續任務( ContinueWith結果)。 但當你這樣做時, ContinueWith主體就會結束

return ags.BulkEditAgenda(currentAgendas);

因此, BulkEditAgenda任務完成之前可能會繼續延續(您不會以任何方式等待BulkEditAgenda完成)。 所以這一行

await agendasTransitionTask;

BulkEditAgenda仍在進行中時返回。 為了進一步說明,請注意從ExecuteAgendas返回的是Task<Task>並且await agendasTransitionTask結果是Task ,它代表您正在運行的BulkEditAgenda

要修復,只需像在其他地方一樣使用async \\ await:

private async Task ExecuteAgendas() {
   var currentAgengas = await ags.GetAgendas();            
   foreach (var item in currentAgendas) {    
       // do stuff            
   }
   await ags.BulkEditAgenda(currentAgendas);
}

暫無
暫無

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

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