Saya baru-baru ini membaca beberapa kode yang menggunakan banyak metode async, tetapi kadang-kadang perlu menjalankannya secara sinkron. Kode tidak:
Foo foo = GetFooAsync(...).GetAwaiter().GetResult();
Apakah ini sama dengan
Foo foo = GetFooAsync(...).Result;
c#
async-await
Jay Bazuzi
sumber
sumber
GetResult
: "Jenis ini dan anggotanya dimaksudkan untuk digunakan oleh kompiler." Orang lain seharusnya tidak menggunakannya.async
/await
metode dalam MVC)Jawaban:
Kurang lebih. Satu perbedaan kecil: jika
Task
gagal,GetResult()
hanya akan melempar pengecualian yang disebabkan secara langsung, sementaraTask.Result
akan melemparAggregateException
. Namun, apa gunanya menggunakan keduanya saat ituasync
? Opsi 100x lebih baik adalah menggunakanawait
.Juga, Anda tidak seharusnya menggunakannya
GetResult()
. Ini dimaksudkan hanya untuk penggunaan kompiler, bukan untuk Anda. Tetapi jika Anda tidak ingin yang menggangguAggregateException
, gunakan itu.sumber
async Task
tes unit pendukung , dan miliki untuk beberapa waktu sekarang.The 100x better option is to use await.
Saya benci pernyataan seperti ini, jika saya bisa menamparawait
di depannya saya akan. Tapi, ketika saya mencoba untuk mendapatkan kode async bekerja terhadap kode non-async seperti apa yang sering terjadi kepada saya banyak di Xamarin, saya akhirnya harus menggunakan hal-hal sepertiContinueWith
banyak dalam rangka untuk membuatnya tidak deadlock UI. Sunting: Saya tahu ini sudah tua, tetapi itu tidak mengurangi rasa frustrasi saya menemukan jawaban yang menyatakan ini tanpa ada alternatif untuk situasi di mana Anda tidak bisa hanya menggunakanawait
.Task.GetAwaiter().GetResult()
lebih disukai daripadaTask.Wait
danTask.Result
karena menyebarkan pengecualian daripada membungkusnya dalamAggregateException
. Namun, ketiga metode ini berpotensi menyebabkan masalah kebuntuan dan masalah pool thread. Mereka semua harus dihindari demiasync/await
.Kutipan di bawah ini menjelaskan mengapa
Task.Wait
danTask.Result
tidak hanya berisi perilaku propagasi pengecualianTask.GetAwaiter().GetResult()
(karena "bilah kompatibilitas sangat tinggi").https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/
http://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html
sumber
Task.GetAwaiter().GetResult()
setara denganawait task
. Saya menganggap opsi pertama digunakan ketika metode tidak dapat ditandai denganasync
(misalnya konstruktor). Apakah itu benar? Jika ya, maka itu bertabrakan dengan jawaban teratas @ It'sNotALieTask.GetAwaiter().GetResult()
lebih setara denganTask.Wait
danTask.Result
(dalam hal ketiganya akan memblokir secara serempak dan memiliki potensi kebuntuan), tetapiTask.GetAwaiter().GetResult()
memiliki perilaku propagasi pengecualian dari tugas yang menunggu.https://github.com/aspnet/Security/issues/59
sumber
Task.WhenAll(task1, task2).GetAwaiter().GetResult();
.Perbedaan lainnya adalah ketika
async
fungsi kembali hanyaTask
daripadaTask<T>
Anda tidak dapat menggunakanSedangkan
masih bekerja.
Saya tahu kode contoh dalam pertanyaan adalah untuk kasus ini
Task<T>
, namun pertanyaannya ditanyakan secara umum.sumber
Result
denganGetIntAsync()
yang kembaliTask<int>
tidak hanyaTask
. Saya sarankan Anda untuk membaca jawaban saya lagi.GetFooAsync(...).Result
berada di dalam fungsi yang kembaliTask
. Ini sekarang masuk akal, karena tidak ada Properti kosong di C # (Task.Result
adalah properti), tetapi Anda tentu saja dapat memanggil metode void.Seperti yang sudah disebutkan jika bisa digunakan
await
. Jika Anda perlu menjalankan kode secara sinkron seperti yang Anda sebutkan.GetAwaiter().GetResult()
,.Result
atau.Wait()
berisiko untuk kebuntuan seperti yang banyak dikatakan dalam komentar / jawaban. Karena sebagian besar dari kita suka oneliners Anda dapat menggunakannya untuk.Net 4.5<
Memperoleh nilai melalui metode async:
Sinkron memanggil metode async
Tidak ada masalah jalan buntu yang akan terjadi karena penggunaan
Task.Run
.Sumber:
https://stackoverflow.com/a/32429753/3850405
sumber
sumber: c # 7.0 secara singkat
sumber