异常没有冒泡
Exception is not bubbling up
我正在尝试捕获抛出的异常,但它没有冒泡到调用它的地方。它在 InsertNewUser
的 catch 块中中断,说
"An exception of type 'System.Exception' occurred in PeakPOS.exe but was not handled in user code"
如果我单击调试器继续,它会转到某个名为 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;
}
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
这是 async
操作的预期行为。您的代码 handles/catches 从方法的同步部分抛出异常,但让应用程序范围处理异步部分。
如果您在 InsertNewUser
方法的第一行(同步部分)显式抛出异常,您可以观察到预期的行为。
修复:正确 await
您的 async
方法。
// must return at least `Task` to be awaitable
public static async Task InsertNewUser(...
比await
的方法(注意"async is viral" - Async/Await
最佳实践):
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
是不好的做法,应该只用于表单事件。
我遇到异常挂起的问题,但这是因为我使用 await 从 Web 服务调用 Web 服务。我的解决方法是应用 ...
.ConfigureAwait(continueOnCapturedContext: false)
...在我的内部网络服务调用中。现在,当内部 Web 服务生成异常时,我收到了预期的异常。
我正在尝试捕获抛出的异常,但它没有冒泡到调用它的地方。它在 InsertNewUser
的 catch 块中中断,说
"An exception of type 'System.Exception' occurred in PeakPOS.exe but was not handled in user code"
如果我单击调试器继续,它会转到某个名为 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;
}
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
这是 async
操作的预期行为。您的代码 handles/catches 从方法的同步部分抛出异常,但让应用程序范围处理异步部分。
如果您在 InsertNewUser
方法的第一行(同步部分)显式抛出异常,您可以观察到预期的行为。
修复:正确 await
您的 async
方法。
// must return at least `Task` to be awaitable
public static async Task InsertNewUser(...
比await
的方法(注意"async is viral" - Async/Await
最佳实践):
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
是不好的做法,应该只用于表单事件。
我遇到异常挂起的问题,但这是因为我使用 await 从 Web 服务调用 Web 服务。我的解决方法是应用 ...
.ConfigureAwait(continueOnCapturedContext: false)
...在我的内部网络服务调用中。现在,当内部 Web 服务生成异常时,我收到了预期的异常。