Verilen üç görevi - FeedCat()
, SellHouse()
veBuyCar()
, iki ilginç durumlar vardır: ya onlar (nedense, belki de önbelleğe veya bir hata) tüm komple eşzamanlı veya onlar değil.
Diyelim ki sorudan:
Task<string> DoTheThings() {
Task<Cat> x = FeedCat();
Task<House> y = SellHouse();
Task<Tesla> z = BuyCar();
// what here?
}
Şimdi, basit bir yaklaşım şöyle olacaktır:
Task.WhenAll(x, y, z);
ancak ... sonuçların işlenmesi için uygun değildir; tipik olarak bunu yapmak await
isteriz:
async Task<string> DoTheThings() {
Task<Cat> x = FeedCat();
Task<House> y = SellHouse();
Task<Tesla> z = BuyCar();
await Task.WhenAll(x, y, z);
// presumably we want to do something with the results...
return DoWhatever(x.Result, y.Result, z.Result);
}
ancak bu çok fazla yük oluşturur ve çeşitli dizileri ( params Task[]
dizi dahil ) ve listeleri (dahili olarak) ayırır. Çalışıyor, ama harika IMO değil. Birçok yönden bir işlemi kullanmak daha kolaydırasync
ve await
her biri sırayla:
async Task<string> DoTheThings() {
Task<Cat> x = FeedCat();
Task<House> y = SellHouse();
Task<Tesla> z = BuyCar();
// do something with the results...
return DoWhatever(await x, await y, await z);
}
Kullanarak yukarıdaki bazı yorumlar, aksine await
yerine Task.WhenAll
markaların fark görevleri (eş zamanlı, sıralı, vs) çalıştırmak nasıl. En yüksek düzeyde, / için iyi derleyici desteğinden Task.WhenAll
önce gelir ve bu şeyler olmadığında yararlı oldu . Ayrıca, 3 gizli görev yerine rastgele bir dizi göreviniz olduğunda da kullanışlıdır.async
await
Ancak: devam için çok fazla derleyici gürültüsü üreten async
/ await
üreten bir sorun var . O görevler olması mümkündür olabilir aslında eşzamanlı tamamlamak, o zaman uyumsuz bir yedek kullanımıyla bir senkron yolunda inşa ederek bu optimize edebilirsiniz:
Task<string> DoTheThings() {
Task<Cat> x = FeedCat();
Task<House> y = SellHouse();
Task<Tesla> z = BuyCar();
if(x.Status == TaskStatus.RanToCompletion &&
y.Status == TaskStatus.RanToCompletion &&
z.Status == TaskStatus.RanToCompletion)
return Task.FromResult(
DoWhatever(a.Result, b.Result, c.Result));
// we can safely access .Result, as they are known
// to be ran-to-completion
return Awaited(x, y, z);
}
async Task Awaited(Task<Cat> a, Task<House> b, Task<Tesla> c) {
return DoWhatever(await x, await y, await z);
}
Bu "eşzamansız geri dönüş ile eşitleme" yaklaşımı, özellikle eşzamanlı tamamlamaların nispeten sık olduğu yüksek performanslı kodda giderek yaygınlaşmaktadır. Tamamlamanın her zaman gerçekten eşzamansız olması durumunda hiç yardımcı olmayacağını unutmayın.
Burada geçerli olan ek şeyler:
son C # ile, ortak bir model, async
geri dönüş yöntemi genellikle yerel bir işlev olarak uygulanır:
Task<string> DoTheThings() {
async Task<string> Awaited(Task<Cat> a, Task<House> b, Task<Tesla> c) {
return DoWhatever(await a, await b, await c);
}
Task<Cat> x = FeedCat();
Task<House> y = SellHouse();
Task<Tesla> z = BuyCar();
if(x.Status == TaskStatus.RanToCompletion &&
y.Status == TaskStatus.RanToCompletion &&
z.Status == TaskStatus.RanToCompletion)
return Task.FromResult(
DoWhatever(a.Result, b.Result, c.Result));
// we can safely access .Result, as they are known
// to be ran-to-completion
return Awaited(x, y, z);
}
tercih ValueTask<T>
etmek Task<T>
çok farklı dönüş değerleri ile şimdiye tamamen eşzamanlı şeylerin iyi bir şans varsa:
ValueTask<string> DoTheThings() {
async ValueTask<string> Awaited(ValueTask<Cat> a, Task<House> b, Task<Tesla> c) {
return DoWhatever(await a, await b, await c);
}
ValueTask<Cat> x = FeedCat();
ValueTask<House> y = SellHouse();
ValueTask<Tesla> z = BuyCar();
if(x.IsCompletedSuccessfully &&
y.IsCompletedSuccessfully &&
z.IsCompletedSuccessfully)
return new ValueTask<string>(
DoWhatever(a.Result, b.Result, c.Result));
// we can safely access .Result, as they are known
// to be ran-to-completion
return Awaited(x, y, z);
}
Mümkünse, tercih IsCompletedSuccessfully
etmek Status == TaskStatus.RanToCompletion
; bu artık .NET Core'da Task
ve her yerde varValueTask<T>