【问题标题】:Cancel async task?取消异步任务?
【发布时间】:2019-08-09 20:30:56
【问题描述】:

我的代码没有正确取消任务,我仍然在图表中看到我的系列正在为foreach 循环中的下一个系列绘制...不确定我在这里做错了什么此时退出并取消所有异步任务...有什么想法吗?

    private void StartTest_Click(object sender, RoutedEventArgs e)
    {
        var cancellationTokenSource = new CancellationTokenSource();
        if (_isRunning)
        {
            cancellationTokenSource.Cancel();
        }

        _isRunning = !_isRunning;
        Start(cancellationTokenSource.Token);
    }

    private async void Start(CancellationToken cancellationToken)
    {
        foreach (var buttonSelected in selectedButtons)
        {
            // If cancellation requested
            if (cancellationToken.IsCancellationRequested)
                break;

            // Retrieve series to reflect changes on
            var seriesToChange = Model.Series.Where(x => x.Title == buttonSelected.Name).ToArray();

            // Create timer
            var timerForPlotting = new DispatcherTimer();
            if (seriesToChange .Length == 1)
            {
                // Set the series to visible
                seriesToChange [0].IsVisible = true;

                timerForPlotting.Interval = TimeSpan.FromMilliseconds(50);
                timerForPlotting.Tick += (object s, EventArgs a) => PlotSeriesPoints_Tick(s, a, seriesToChange [0]);
            }

            // Start
            InitiateTimerWithButtonUIChange(timerForPlotting, buttonSelected, false);

            // Set the task to only take a couple of seconds
            await Task.Delay(2000);

            // End
            InitiateTimerWithButtonUIChange(timerForPlotting, buttonSelected, true);
        }
    }

    private void InitiateTimerWithButtonUIChange(DispatcherTimer timer, Button buttonSelected, bool isFinished)
    {
        if (!isFinished)
        {
            timer.Start();
            buttonSelected.Background = resourceDictionary["Processing"] as Brush;
        }
        else
        {
            timer.Stop();
            buttonSelected.Background = resourceDictionary["ColourActive"] as Brush;

            // Reset
            time = 0;
        }
    }

【问题讨论】:

  • StartTest_Click 方法中的逻辑看起来完全是古怪的。
  • 您总是在重新创建 CancellationTokenSource,因此正在运行的任务中使用的不是您要取消的。

标签: c# async-await


【解决方案1】:

尝试在您用于创建传递给Start 的令牌的实际CancellationTokenSource 上调用Cancel()

CancellationTokenSource cancellationTokenSource;
private void StartTest_Click(object sender, RoutedEventArgs e)
{
    if (cancellationTokenSource != null)
    {
        cancellationTokenSource.Cancel();
        cancellationTokenSource.Dispose();
    }

    cancellationTokenSource = new CancellationTokenSource();
    _isRunning = !_isRunning;
    Start(cancellationTokenSource.Token);
}

【讨论】:

  • 难道你还必须在 if 语句中将 null 分配给 cancellationTokenSource 吗?
  • @ColinM 为什么要分配 null?之后将在 cancelTokenSource 上分配一个新值
  • 没关系,忽略我 - 没有返回语句,因此代码将继续分配到它分配的位置。我的道歉..
  • 我的示例确实停止了,但随后它立即再次调用 Start。因此,您正在取消在每次点击时开始一个新任务。
  • 好吧,如果您还有其他问题,请提出一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
相关资源
最近更新 更多