Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // from:
- // https://github.com/AngryCarrot789/FrameControlEx
- private bool isHandlingSyncClosing;
- private bool isHandlingAsyncClose;
- private bool? closeEventResult;
- protected sealed override void OnClosing(CancelEventArgs e) {
- if (this.isHandlingSyncClosing || this.isHandlingAsyncClose) {
- return;
- }
- try {
- this.isHandlingSyncClosing = true;
- this.OnClosingInternal(e);
- if (this.closeEventResult.HasValue) {
- try { // try finally juuust in case...
- e.Cancel = !this.closeEventResult.Value; // true = close, false = do not close
- }
- finally {
- this.closeEventResult = null;
- }
- }
- else {
- e.Cancel = true;
- }
- }
- finally {
- this.isHandlingSyncClosing = false;
- }
- }
- /*
- async void is required here
- OnClosing is fired, that sets isHandlingSyncClosing to true and invokes this method which awaits CloseAsync()
- During the invocation of CloseAsync, If the call does not require
- real async (e.g. does not use Task.Delay() or whatever):
- CloseAsync will return in the same execution context as OnClosing, meaning isHandlingSyncClosing
- stays true, and OnClosing can access closeEventResult and set the e.Cancel accordingly
- However, if the call chain in CloseAsync uses Task.Delay() or something which returns
- a task that is incomplete by the time the async state machine comes to actually "awaiting" it,
- then the behaviour changes:
- OnClosing returns before CloseAsync is completed, setting isHandlingSyncClosing to false, meaning that
- CloseAsyncInternal will manually close the window itself because the original OnClosing was cancelled
- */
- private async void OnClosingInternal(CancelEventArgs e) {
- bool result = await this.CloseAsync();
- if (this.isHandlingSyncClosing) {
- this.closeEventResult = result;
- }
- }
- /// <summary>
- /// Closes the window
- /// </summary>
- /// <returns>Whether the window was closed or not</returns>
- public Task<bool> CloseAsync() {
- // return await await Task.Run(async () => await DispatcherUtils.InvokeAsync(this.Dispatcher, this.CloseAsyncInternal));
- return DispatcherUtils.Invoke(this.Dispatcher, this.CloseAsyncInternal);
- }
- private async Task<bool> CloseAsyncInternal() {
- if (await this.OnClosingAsync()) {
- if (!this.isHandlingSyncClosing) {
- try {
- this.isHandlingAsyncClose = true;
- await DispatcherUtils.InvokeAsync(this.Dispatcher, this.Close);
- return true;
- }
- finally {
- this.isHandlingAsyncClose = false;
- }
- }
- return true;
- }
- else {
- return false;
- }
- }
- /// <summary>
- /// Called when the window is trying to be closed
- /// </summary>
- /// <returns>True if the window can close, otherwise false to stop it from closing</returns>
- protected virtual Task<bool> OnClosingAsync() {
- return Task.FromResult(true);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement