繁体   English   中英

CancellationTokenSource.Cancel在WPF应用程序退出期间不起作用

[英]CancellationTokenSource.Cancel doesn't work during WPF app exit

这是带有取消代码段的简单异步调用。 该代码位于WPF应用程序类中。 如果我通过WPF UI命令调用Cancel方法,则异步方法将正确退出。 但是,如果在OnExit方法期间调用Cancel,则不会发生任何事情。 我的实际代码需要OnExit调用,因为async方法使用应正确清理的IO资源。

有任何想法吗?

编辑:预期的行为是,在调用cancel时Task.Delay方法应引发OperationCancelledException。 我想知道的是为什么它在应用程序退出时不显示,以及是否有解决方法使其正常运行。

public partial class App : Application {
    protected override void OnStartup(StartupEventArgs e) {
        base.OnStartup(e);
        ListenAsync(source.Token);
    }

    ManualResetEvent waitHandle = new ManualResetEvent(false);
    CancellationTokenSource source = new CancellationTokenSource();

    public void Cancel() {
        source.Cancel();
    }

    async void ListenAsync(CancellationToken token) {
        try {
            while (true) {
                await Task.Delay(300000, token);
            }
        } catch (OperationCanceledException) {
            Console.WriteLine("Cancelled");
        } catch (Exception err) {
            Console.WriteLine(err.Message);
        } finally {
            Console.WriteLine("Terminate");
            waitHandle.Set();
        }
    }

    protected override void OnExit(ExitEventArgs e) {
        Cancel();
        waitHandle.WaitOne();
        base.OnExit(e);
    }
}

找到了问题。

WPF应用程序退出期间的Cancel调用与ListenAsync函数在同一同步上下文上。 由于该线程被waitHandle.WaitOne阻止,因此ListenAsync方法无法在同一同步上下文上继续执行。

可以通过将异步调用更改为来解决该问题

await Task.Delay(300000, token).ConfigureAwait(false);

这使ListenAsync函数的其余部分可以保留在Task.Delay函数的同步上下文中。

不知道这是否可以解决当前的问题,但是根据您发布的代码上下文,很可能您可以使用令牌对象的IsCancellationRequested属性并检查该属性是否有取消请求,并像这样退出监听循环

async void ListenAsync(CancellationToken token) {
    try {
        while (true) 
        {
            if(token.IsCancellationRequested)
              break;

            await Task.Delay(300000, token);
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM