Wpf child form, OnClosing event and await -
i have child form launched form parent form with:
configform cfg = new configform(); cfg.showdialog();
this child form used configure application parameters. want check if there changes not saved, , if so, warn user. on onclosing event declared way:
private async void childformclosing(object sender, system.componentmodel.canceleventargs e) { // here call function compare current config saved config bool isuptated = checkunsavedchanges(); // if updated false, means there unsaved changes... if (!isupdated) { e.cancel = true; // @ point create messagedialog (mahapps) warn user unsaved changes... messagedialogstyle style = messagedialogstyle.affirmativeandnegative; var metrodialogsettings = new metrodialogsettings() { affirmativebuttontext = "close", negativebuttontext = "cancel" }; var result = await this.showmessageasync("config", "there unsaved changes, want exit?", style, metrodialogsettings); // if press close, want close child form , go parent... if (result == messagedialogresult.affirmative) { e.cancel = false; } } }
my logic says if declare e.cancel false continue closing form, doesn't happen, child form remains open.
my guess async call doing don't understand, because if declare childformclosing in way:
private async void childformclosing(object sender, system.componentmodel.canceleventargs e) { bool isuptated = checkunsavedchanges(); e.cancel = true; if (!isupdated) { messagedialogstyle style = messagedialogstyle.affirmativeandnegative; var metrodialogsettings = new metrodialogsettings() { affirmativebuttontext = "close", negativebuttontext = "cancel" }; var result = await this.showmessageasync("config", "there unsaved changes, want exit?", style, metrodialogsettings); if (result == messagedialogresult.affirmative) { e.cancel = false; } } else { e.cancel = false; } }
the final else e.cancel = false works , child form closed...
any clue? thanks!
since method event handler window, called on ui thread already, there no need show message box asynchronously.
as strange behavior seeing, related await
in event handler. when await
method call, happening until await
executed normal, once await
statement reach control returns caller. once method await
ed upon returns, rest of original method executes.
the code fires onclosing
event not designed asynchronous event handlers in mind, assumes if event handler returns, has finished whatever work needs do. since event handler sets canceleventargs.cancel
true
before await
s on method call, caller event handler sees set true
, doesn't close form.
this why showing message box synchronously works: entire method executed before control returns caller, canceleventargs.cancel
set expected value.
raymond chen posted 2 articles async
might interesting reading: crash course in async , await , the perils of async void. second article describes why async
event handlers tend not work how expect them to.
Comments
Post a Comment