Saya mendapat panggilan yang saya lakukan dari dalam C#
aplikasi metro berbasis xaml di CP Win8; panggilan ini hanya mengenai layanan web dan mengembalikan data JSON.
HttpMessageHandler handler = new HttpClientHandler();
HttpClient httpClient = new HttpClient(handler);
httpClient.BaseAddress = new Uri("http://192.168.1.101/api/");
var result = await httpClient.GetStreamAsync("weeklyplan");
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(WeeklyPlanData[]));
return (WeeklyPlanData[])ser.ReadObject(result);
Itu hang di await
tapi panggilan http benar-benar kembali segera (dikonfirmasi melalui fiddler); seolah-olah await
diabaikan dan hanya tergantung di sana.
Sebelum Anda bertanya - YA - kapabilitas Jaringan Pribadi telah diaktifkan.
Ada ide mengapa ini akan menggantung?
c#
asynchronous
async-await
dotnet-httpclient
keithwarren7
sumber
sumber
async
metode itu? Bukankah itu membuat pengecualian?Jawaban:
Lihat jawaban atas pertanyaan saya ini yang tampaknya sangat mirip.
Sesuatu untuk dicoba: panggil
ConfigureAwait(false)
Tugas yang dikembalikan olehGetStreamAsync()
. MisalnyaApakah ini berguna atau tidak tergantung pada bagaimana kode Anda di atas dipanggil - dalam kasus saya memanggil
async
metode menggunakanTask.GetAwaiter().GetResult()
menyebabkan kode hang.Ini karena
GetResult()
memblokir utas saat ini hingga Tugas selesai. Ketika tugas selesai, ia mencoba untuk masuk kembali ke konteks utas tempat ia dimulai tetapi tidak bisa karena sudah ada utas dalam konteks itu, yang diblokir oleh panggilan keGetResult()
... deadlock!Posting MSDN ini membahas sedikit detail tentang bagaimana .NET menyinkronkan utas paralel - dan jawaban yang diberikan untuk pertanyaan saya sendiri memberikan beberapa praktik terbaik.
sumber
Sekadar pemberitahuan - jika Anda melewatkan menunggu di tingkat atas dalam pengontrol ASP.NET, dan Anda mengembalikan tugas alih-alih hasilnya sebagai respons, itu sebenarnya hanya hang di panggilan tunggu bersarang tanpa kesalahan. Kesalahan konyol, tetapi jika saya melihat posting ini, itu mungkin telah menghemat waktu saya memeriksa kode untuk sesuatu yang aneh.
sumber
Penafian: Saya tidak suka solusi ConfigureAwait () karena menurut saya solusi ini tidak intuitif dan sulit untuk diingat. Sebagai gantinya saya sampai pada kesimpulan untuk membungkus panggilan metode yang tidak ditunggu di Task.Run (() => myAsyncMethodNotUsingAwait ()). Ini sepertinya berhasil 100% tetapi mungkin hanya kondisi balapan !? Saya tidak begitu yakin apa yang sebenarnya terjadi. Kesimpulan ini mungkin salah dan saya mempertaruhkan poin StackOverflow saya di sini untuk belajar dari komentar :-P. Mohon dibaca!
Saya baru saja mengalami masalah seperti yang dijelaskan dan menemukan info selengkapnya di sini .
Pernyataannya adalah: "Anda tidak dapat memanggil metode asinkron"
dari metode yang memblokir
Dalam kasus saya, saya tidak dapat mengubah metode panggilan dan itu tidak asinkron. Tapi saya sebenarnya tidak peduli dengan hasilnya. Seperti yang saya ingat, itu juga tidak berhasil menghapus .Result dan menunggu hilang.
Jadi saya melakukan ini:
Dalam kasus saya, saya tidak peduli dengan hasil dalam memanggil metode non-async tetapi saya rasa itu cukup umum dalam kasus penggunaan ini. Anda dapat menggunakan hasilnya dalam metode pemanggilan async.
sumber