例外不是冒泡

Shr*_*ers 7 c# exception-handling try-catch

我试图抓住抛出的异常,但它没有冒泡到它被调用的地方.它突然陷入InsertNewUser困境,说道

"PeakPOS.exe中出现类型'System.Exception'的例外,但未在用户代码中处理"

如果我点击调试器继续,它会转到一个被调用的文件,App.g.i.cs并在我不理解的行上断开,但与休息时的调试有关.该应用程序在此之后终止.

为什么在重新抛出然后重新捕获和处理(待处理)时异常未处理?


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;
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

App.gics

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

Ale*_*kov 5

这是async操作的预期行为。您的代码可以处理/捕获从方法的同步部分抛出的异常,但可以让应用程序范围的句柄处理异步部分。

如果在InsertNewUser方法的第一行(同步部分)上显式抛出异常,则可以观察到预期的行为。

解决:正确使用await您的async方法。

// must return at least `Task` to be awaitable
public static async Task InsertNewUser(...
Run Code Online (Sandbox Code Playgroud)

而不是await方法(请注意,“异步是病毒式的” -Async / Await最佳实践):

   try
   {
        await PeakDB.InsertNewUser(TempUser, salt, hash);
    }
    catch (Exception e) ...
Run Code Online (Sandbox Code Playgroud)

或者至少是.Wait如果它控制台应用程序(WPF / WinForm / Asp.Net将死锁- 等待vs Task.Wait-死锁?):

   try
   {
        PeakDB.InsertNewUser(TempUser, salt, hash).Wait();
    }
    catch (Exception e) ...
Run Code Online (Sandbox Code Playgroud)

如果您不能执行任何操作-至少要对async和“旧的async委托”使用正确的“即弃”功能来调用async void方法。

注意:这async void是错误的做法,应仅用于表单事件。