Pertanyaan Melempar pengecualian dari ContinueWith


Saya mencoba untuk membungkus pengecualian yang dapat dilemparkan oleh tugas async menggunakan ContinueWith(). Jika saya hanya membuang dari tindakan kelanjutan hal-hal tampaknya bekerja, tetapi debugger saya mengklaim pengecualian tidak ditangani. Apakah saya melakukan kesalahan atau apakah ini masalah Visual Studio? Apakah ada cara yang lebih bersih untuk melakukan ini, atau cara untuk mengatasi debugger saya berhenti pada apa yang akhirnya merupakan pengecualian yang ditangani?

Tes di bawah ini berlalu dan mencetak "pengecualian yang dibungkus tertangkap seperti yang diharapkan", tetapi ketika saya men-debug-nya throw new CustomException garis menunjukkan sebagai "tidak tertangani oleh kode pengguna".

var task = DoWorkAsync().ContinueWith(t => {
    throw new CustomException("Wrapped", t.Exception.InnerException);  // Debugger reports this unhandled
}, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);

try {
    task.Wait();
    Assert.Fail("Expected work to fail");
} catch (AggregateException ag) {
    if (!(ag.InnerException is CustomException))
        throw;
}
Console.WriteLine("Caught wrapped exception as expected");

5
2017-07-26 21:24


asal


Jawaban:


Ketika "Just My Code" diaktifkan, Visual Studio dalam beberapa kasus akan memutuskan pada baris yang melempar pengecualian dan menampilkan pesan kesalahan yang mengatakan "pengecualian tidak ditangani oleh kode pengguna." Kesalahan ini jinak. Anda dapat menekan F5 untuk melanjutkan dan melihat perilaku penanganan pengecualian yang ditunjukkan dalam contoh-contoh ini. Untuk mencegah Visual Studio melanggar kesalahan pertama, cukup hapus centang pada kotak centang "Just My Code" di bawah Tools, Options, Debugging, General.

Dari http://msdn.microsoft.com/en-us/library/dd997415.aspx


10
2017-12-19 22:17



Anda tidak tampak seperti "membungkus" pengecualian dengan kelanjutan, Anda tampaknya melemparkan pengecualian dalam kelanjutannya. Jika DoWorkAsync adalah apa yang bisa melempar pengecualian, saya akan "membungkus" itu dalam kelanjutan sebagai berikut:

DoWorkAsync().ContinueWith(t=>{
 Console.WriteLine("Error occurred: " + t.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);

Sebagai alternatif, jika Anda ingin "menangani" pengecualian di luar metode async, Anda dapat melakukan ini:

var task = DoWorkAsync();

task.Wait();
if(task.Exception != null)
{
  Console.WriteLine("Error occurred: " + task.Exception);
}

Jika Anda ingin mengubah pengecualian terlempar, Anda dapat melakukan sesuatu seperti ini:

var task = DoWorkAsync().ContinueWith(t=>{
 if(t.Exception.InnerExceptions[0].GetType() == typeof(TimeoutException))
 {
     throw new BackoffException(t.Exception.InnerExceptions[0]);
 }
}, TaskContinuationOptions.OnlyOnFaulted);

Dan Anda bisa mengatasinya BackoffException seperti ini:

if(task.IsFaulted)
{
   Console.WriteLine(task.Exception.InnerExceptions[0]);
   // TODO: check what type and do something other than WriteLine.
}

4
2017-07-26 21:33