为什么如果我尝试使用CancellationToken.Cancel()停止任务,那么实际任务就会卡在Task.Wait()上?

时间:2018-07-04 11:58:02

标签: c# task cancellationtokensource

按照我的MSDN提供的示例,我试图在C#中实现任务取消。 我有一个带有图表的Windows窗体应用程序,该图表显示了来自外部设备的数据和一个“开始/停止”按钮。这就是按钮内的代码,或多或少:

if (drawGraph_task == null)
{
    cts = new System.Threading.CancellationTokenSource();
    token = cts.Token;
    drawGraph_task = new Task(() => 
    {
        this.Invoke(new InvokeDelegate(this.myChart.Series[0].Points.Clear));

        while (true)
        {
            // get x and y from device using external lib
            this.Invoke(new addPointXYDelegate(this.myChart.Series[0].Points.AddXY), new object[] { x, y });
            this.Invoke(new InvokeDelegate(this.chart_pressure.Update)); // update graph

            if (token.IsCancellationRequested)
            {
                return;
            }

        }
    }, token);
    this.button_main_start.Text = "Stop";
    drawGraph_task.Start();                
}
else
{
    cts.Cancel();

    try
    {
        drawGraph_task.Wait();
    }
    catch (AggregateException ae)
    {
        // do nothing
    }
    finally
    {
        cts.Dispose();
        drawGraph_task.Dispose();
        drawGraph_task = null;
        this.button_main_start.Text = "Restart";
    }
}

为什么代码仍然停留在drawGraph_task.Wait()调用中? 我尝试在任务中使用token.throwIfCancellationRequested(),但有时我会产生相同的效果,有时异常不会被捕获。我究竟做错了什么? 为了完整起见,x和y的计算涉及:

  • MathNet插值库
  • 调用内部制造的库,以进行特定于协议的通信,以等待事件发生(它总是启动的,因此这不是问题的根源)

1 个答案:

答案 0 :(得分:0)

Task.Wait()是同步的。如果由于调用Invoke()而发生这种情况,您可以返回此方法,则将出现死锁。达到卡滞状态时,使用调试器检查调用堆栈的状态。