【问题标题】:WP8.1 - CancellationToken and async still await forever and never endWP8.1 - CancellationToken 和 async 仍然永远等待并且永远不会结束
【发布时间】:2014-11-07 01:46:24
【问题描述】:

我有一个非常奇怪的问题,我不知道如何解决。 我在不同的类中有这两种方法。 第一个在 CommandBar 中的按钮被按下时触发。

编辑:我创建了两个类似但较小的方法来向您展示问题:

    private async void runCode(object sender, RoutedEventArgs e)
    {
        BottomAppBar.IsEnabled = false;
        object result = await endlessLoopTest();
        BottomAppBar.IsEnabled = true;
    }

    private async Task<object> endlessLoopTest()
    {
        var tokenSource = new System.Threading.CancellationTokenSource(500);
        try
        {
            await Task.Run(() =>
            {
                while (true)
                {
                    //Infinite loop to test the code
                }
            }, tokenSource.Token);
            return null;
        }
        catch (OperationCanceledException)
        {
            return new TextBlock();
        }
    }

我添加了一个在 1500 毫秒后过期的取消令牌(我假设如果解释器需要更长的时间来处理代码,它已经被困在一个循环中)。

我第一次尝试它通常可以工作,但如果我再试一次,CommandBar 按钮将永远不会再次启用,所以我认为任务正在等待永远,我不知道为什么,因为我添加了 cancelToken .

你知道这里有什么问题吗? 感谢您的帮助!

塞尔吉奥

【问题讨论】:

  • 请提供更好的代码示例。一种简洁,但实际上可以由其他人编译和运行。如果你也能省去脏话就好了。见stackoverflow.com/help/mcve
  • 大声笑这是我正在解释的语言的实际名称啊哈哈哈我忘了删掉它,抱歉 :) 我用两个重现问题的小方法编辑了我的帖子,再次感谢您的帮助!

标签: c# xaml windows-store-apps windows-phone-8.1 win-universal-app


【解决方案1】:

你大约是那里的 2/3。当使用CancellationToken + CancellationTokenSournce 时,必须询问令牌是否被取消。有多种订阅方式,包括调用令牌的ThrowIfCancelledRequest 方法或检查令牌的Boolean 属性IsCancellationRequestedbreak 退出循环。见Cancellation in Managed Threads

这是一个可以在控制台应用程序中运行的小示例。请注意,在基于 UI 的应用中,请使用 await,而不是 Task.Wait()

    private static void CancelTask()
    {
        CancellationTokenSource cts = new CancellationTokenSource(750);
        Task.Run(() =>
        {
            int count = 0;
            while (true)
            {
                Thread.Sleep(250);
                Console.WriteLine(count++);
                if (cts.Token.IsCancellationRequested)
                {
                    break;
                }
            }
        }, cts.Token).Wait();
    }

结果是0 1 2,然后任务和程序退出。

【讨论】:

  • 谢谢,有效!可能进入无限循环的方法是一种递归方法,其中也有一个 goto,我在跳转标签之后添加了一个 ThrowIfCancelledRequest(),它可以工作:D 我只是不明白调试时怎么可能在我添加 Throw 方法之前,带有断点的应用程序可以正常工作。我的意思是,任务还是被取消了。无论如何,非常感谢您的帮助! :)
猜你喜欢
  • 2021-08-05
  • 2019-05-21
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 2021-05-17
相关资源
最近更新 更多