I'm trying to catch a thrown Exception, but it doesn't bubble up to where it was called. It breaks in InsertNewUser
's catch block, saying
"An exception of type 'System.Exception' occurred in PeakPOS.exe but was not handled in user code"
If I click on debugger Continue, it goes to some file called App.g.i.cs
and breaks on a line I don't understand but has something to do with debugging on break. The application terminates after that.
Why is it saying the exception is unhandled when it is being rethrown and then re-caught and handled (to-be handled)?
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
This is expected behavior for async
operation. Your code handles/catches exceptions thrown from synchronous part of the method, but lets application wide handle to deal with async part.
You can observe behavior you expect if you explicitly throw exception on first line of InsertNewUser
method (synchronous part).
Fix: properly await
your async
method.
// must return at least `Task` to be awaitable
public static async Task InsertNewUser(...
And than await
the method (note that "async is viral" - Async/Await
Best Practices):
try
{
await PeakDB.InsertNewUser(TempUser, salt, hash);
}
catch (Exception e) ...
Or at least .Wait
if it console app (WPF/WinForm/Asp.Net will deadlock - await vs Task.Wait - Deadlock?):
try
{
PeakDB.InsertNewUser(TempUser, salt, hash).Wait();
}
catch (Exception e) ...
If you can't do either - at least use proper Fire-and-forget with async vs "old async delegate" to call async void
methods.
Note: async void
is bad practice and should only be used for form events.
I was having a problem where my exceptions would hang, but it was because I was calling a web service from a web service using await. My fix was to apply ...
.ConfigureAwait(continueOnCapturedContext: false)
... on my inner web service call. Now when then inner web service generates an exception I receive the exception as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With