首页 > 解决方案 > 如何在 WPF 关闭事件中使用 DerralManager GetDeferral()?

问题描述

WPF

我正在尝试延迟关闭窗口,直到使用 StephenCleary https://github.com/StephenCleary/AsyncEx的 async/await 库完成所有任务。

事件处理程序委托和事件参数定义:

public delegate void CancelEventHandlerAsync(object sender, CancelEventArgsAsync e);

public class CancelEventArgsAsync : CancelEventArgs
{
    private readonly DeferralManager _deferrals = new DeferralManager();

    public IDisposable GetDeferral()
    {
        return this._deferrals.GetDeferral();
    }

    public Task WaitForDefferalsAsync()
    {
        return this._deferrals.SignalAndWaitAsync();
    }
}

然后在 NewWindowDialog.xaml 后面的代码中,我重写了 OnClosing 事件:

public NewWindowDialog()
        {
            InitializeComponent();

        }

        protected override async void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = true;
            base.OnClosing(e);
            await LaunchAsync();
        }

        private async Task LaunchAsync()
        {
            var vm =(NewProgressNoteViewModel)DataContext;
            var cancelEventArgs = new CancelEventArgsAsync();
            using (var deferral = cancelEventArgs.GetDeferral())
            {
                // a very long procedure!
                await vm.WritingLayer.CompletionAsync();
            }

        }

显然,这失败了,因为 e.Cancel = true 在等待之前执行。那么,在任务完成时(在 WPF 中)正确使用 GetDeferral() 来延迟窗口关闭,我缺少什么。

TIA

编辑:在大家的帮助下,我目前正在使用它。但是,有没有人有关于关闭窗口的延迟模式的一个很好的例子?

谢谢大家。

private bool _handleClose = true;
        protected override async void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            using (new BusyCursor())
            {
                if (_handleClose)
                {
                    _handleClose = false;
                    IsEnabled = false;
                    e.Cancel = true;

                    var vm = (NewProgressNoteViewModel)DataContext;

                    await vm.WritingLayer.SaveAsync();

                    e.Cancel = false;
                    base.OnClosing(e);
                }
            }
        }

标签: c#wpfeventsasync-await

解决方案


你不需要延期。只需将CancelEventArgs.Cancel属性设置为true,等待长时间运行的操作,然后关闭。您可以使用标志来避免多次执行相同的操作:

private bool _handleClose = true;
protected override async void OnClosing(System.ComponentModel.CancelEventArgs e)
{
    if (_handleClose)
    {
        e.Cancel = true;
        await Task.Delay(5000);// a very long procedure!
        _handleClose = false;
        Close();
    }
}

推荐阅读