Почему, если я пытаюсь остановить задачу с помощью CancellationToken.Cancel (), то реальная задача застревает в Task.Wait ()? - PullRequest
0 голосов
/ 04 июля 2018

Я пытаюсь реализовать отмену задачи в C #, следуя примерам, предоставленным моим MSDN. У меня есть приложение Windows Form с графиком, показывающим данные, поступающие с внешних устройств, и кнопкой «Пуск / Стоп». Это код, более или менее, внутри кнопки:

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 () внутри задачи, но иногда у меня был тот же эффект, иногда исключение не ловится моим уловом. Что я делаю неправильно? Для полноты вычисления х и у включает в себя:

  • MathNet Interpolate библиотека
  • вызывает собственную библиотеку для связи по конкретному протоколу, которая предназначена для ожидания события (оно всегда запускалось, поэтому это не является источником проблемы)

1 Ответ

0 голосов
/ 04 июля 2018

Task.Wait () является синхронным. Если случится так, что из-за вызова Invoke () вы сможете вернуться к этому методу, вы получите тупик. Используйте отладчик, чтобы проверить состояние вашего стека вызовов, когда вы достигли застрявшего состояния.

...