2012-10-24 18 views
52

bu düşünün zaman uyumsuz lambda görev tamamlama ve hemen yürütülür sonraki satıra beklemezBen içine zaman uyumsuz lambda ifadesi sarın eğer

Task task = new Task (async() =>{ 
    await TaskEx.Delay(1000); 
}); 
task.Start(); 
task.Wait(); 

çağrı task.Wait() bekliyor, ama olamaz yöntem çağrısı, kod beklendiği gibi çalışır. o döndüren

private static async Task AwaitableMethod() 
{ 
    await TaskEx.Delay(1000);  
} 

sonra inşa (güncellenmiş göre svick gelen açıklama)

await AwaitableMethod(); 
+0

'aslında dönen ve görev .Delay döndü üzerinde Bekle aradığınız AwaitableMethod'() yöntem (Ben bir 'Görev' döndürdüğünü varsayalım). Async lambda'da 'Görev görevinde bekle' diyorsunuz. Ama yine de, hiçbir açıklamam yok. –

+1

“Bekle” ile “Bekle” yi karıştırmaya çok dikkat etmelisiniz. Birçok durumda, bu kilitlenmelere yol açabilir. – svick

+0

@svick harika bir [örnek] (http://stackoverflow.com/a/11179035/815938) 'bekle 'bekle' ile bekle' 'bekle()' – kennyzx

cevap

69
sizin lambda örnekte

Eğer task.Wait() çağırdığınızda, yeni Görev bekleyen değil, gecikme Görev .

Task<Task> task = new Task<Task>(async() => { 
    await Task.Delay(1000); 
}); 
task.Start(); 
task.Wait(); 
task.Result.Wait(); 

Yeni Görevi inşa önlemek olabilir ve sadece yerine iki baş etmenin tek Görevi var:

Func<Task> task = async() => { 
    await TaskEx.Delay(1000); 
}; 
task().Wait(); 
+8

okuma tavsiye [Potansiyel tuzakları async lambdas geçerken önlemek için ] (http://blogs.msdn.com/b/pfxteam/archive/2012/02/08/10265476.aspx) ve [Task.Run vs Task.Factory.StartNew] (http://blogs.msdn.com /b/pfxteam/archive/2011/10/24/10229468.aspx). – Andrew

+1

İlk bekleyiş çok sayıda işlemden geçiyorsa, yine de çift görevleri isteyebilirsiniz. 'Task.Result.Wait()' yerine 'task.Unwrap() işlevini de yapabilirsiniz. Wait()' (veya geçersiz olmayan yöntemler için '()' unwrap). Yeni 'Task.Run' yöntemleri otomatik olarak açıldığından, yalnızca beklenen görevde beklersiniz. –

+4

Acemi olarak, "async" anahtar kelimesiyle daha iyi bir iş yapabilecekleri izlenimine sahibim; çok kafa karıştırıcı. – drowa

6
istediğiniz gecikmeyi almak için ayrıca çıkan Görev beklemek gerekir

TaskEx.RunEx kullanmanız gerekir.

Bu, iç görevi dahili olarak bekleyerek TaskPool üzerinde async yöntemlerini çalıştırmayı destekler. Aksi takdirde, karşı karşıya kaldığınız meseleye girersiniz, sadece dış görev beklenir, ki bu açıkça derhal tamamlanır, ya beklemeye ihtiyaç duyan bir görev bırakmaz ya da sizin durumunuzda (ve hatta daha da kötüsü) boş bir lambda olamaz. bekliyordu.

Alternatif olarak, görevinizi iki kez bekleyerek, dış görevinizi doğru şekilde oluşturmanızı sağlar (şu anda bulunmuyorsunuz).

Güncel kod (sabit): TaskEx.RunEx kullanma

Task task = new Task<Task>(async() =>{ 
    await TaskEx.Delay(1000); 
}); 

task.Start(); 
var innerTask = await task; 
await innerTask; 

: In

Task task = TaskEx.RunEx(async() =>{ // Framework awaits your lambda internally. 
    await TaskEx.Delay(1000); 
}); 

await task; 
+0

Güzel açıklama, ancak TaskEx.Run kodu çalışmıyor, hala aynı sorunu var. – kennyzx

+2

Argh, üzgünüm! .NET 4.5 kullanıyorum ... TaskEx.RunEx yazmayı kastettim. İmzasını TaskEx.Run ile karşılaştırın - neden asenkronizasyon yöntemlerini çalıştırdığınızı anlarsınız. –