2015-04-24 96 views
5

我想趕上拋出異常,但它不起泡到它被稱爲。它打破了InsertNewUser的catch塊,說異常不冒泡

‘類型的異常‘System.Exception的’發生在PeakPOS.exe但在用戶代碼中沒有處理’

如果我點擊調試器繼續,它進入一個名爲App.g.i.cs的文件,並打破了一條我不明白的地方,但與break上的調試有關。應用程序在此之後終止。

爲什麼它在重新拋出然後重新捕獲和處理(待處理)時異常是未處理的?


AccessViewModel.cs

public void SaveNewUser(Popup popup) 
{ 
    UserAccounts.Add(TempUser); 

    string salt = PeakCrypto.GenerateSalt(); 
    string hash = PeakCrypto.GenerateHashedPassword(Password + salt); 
    try 
    { 
     PeakDB.InsertNewUser(TempUser, salt, hash); 
    } 
    catch (Exception e) 
    { 
     //TODO notify user that new account could not be saved 
    } 

    CreateNewAccount(); 

    if (popup != null) 
     popup.IsOpen = false; 
} 

PeakDB.cs

public static async void InsertNewUser(UserAccount user, String salt, String hash) 
{ 
    var db = await DatabaseHelper.GetDatabaseAsync(); 

    try 
    { 
     using (var userStatement = await db.PrepareStatementAsync(
      "INSERT INTO AccessAccounts (FirstName, LastName, Salt, Hash) VALUES(@first, @last, @salt, @hash)")) 
     { 
      userStatement.BindTextParameterWithName("@first", user.FirstName); 
      userStatement.BindTextParameterWithName("@last", user.LastName); 
      userStatement.BindTextParameterWithName("@salt", salt); 
      userStatement.BindTextParameterWithName("@hash", hash); 
      await userStatement.StepAsync(); 
     } 
    } 
    catch(Exception e) 
    { 
     // TODO: log the exception error 
     throw; 
    } 
} 

App.g.i.cs

#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION 
    UnhandledException += (sender, e) => 
    { 
     if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break(); 
    }; 
#endif 
+0

您是否嘗試取消選中「當此異常發生時中斷」並再次運行的複選框?我認爲,在調試模式下,它確實在例外情況下中斷 –

+0

@Saagar:是的。會發生什麼呢,它會發送到App.g.i.cs文件,並像以前一樣中斷if語句,它不會再被中斷。我想知道我是否誤解了try/catch。捕捉到一個不處理它的異常? – ShrimpCrackers

回答

4

這是async操作的預期行爲。你的代碼處理/捕獲從方法的同步部分拋出的異常,但讓應用程序處理異步部分。

如果您在InsertNewUser方法(同步部分)的第一行顯式拋出異常,則可以觀察到您期望的行爲。

修復:正確await您的async方法。

// must return at least `Task` to be awaitable 
public static async Task InsertNewUser(... 

而且比await方法(注意, 「異步是病毒」 - Async/Await Best Practices):

try 
    { 
     await PeakDB.InsertNewUser(TempUser, salt, hash); 
    } 
    catch (Exception e) ... 

,或者至少.Wait如果控制檯應用程序(WPF/WinForm的/ Asp.Net會死鎖 - await vs Task.Wait - Deadlock?):

try 
    { 
     PeakDB.InsertNewUser(TempUser, salt, hash).Wait(); 
    } 
    catch (Exception e) ... 

如果你不能做任何 - 至少要用適當Fire-and-forget with async vs "old async delegate"調用async void方法秒。

注意:async void是不好的做法,只能用於表單事件。

+0

謝謝,阿列克謝。有效。欣賞這些鏈接,因爲我是C#的新手,並且只是簡略地瀏覽了異步/等待功能,並且不太瞭解它。 – ShrimpCrackers

+0

@ShrimpCrackers歡迎。如果您需要使用'async' /'await',我強烈建議在[Stephen Cleary](http://stackoverflow.com/users/263693/stephen-cleary)中查看最重要的答案,然後再進行任何認真的工作區。 –