[英]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);
}
EditNoReconnect
和Save
都是同步方法。
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.