Отменить задачу, запущенную под управлением пользователя - PullRequest
0 голосов
/ 04 апреля 2019

В моем проекте у меня мало пользовательских элементов управления, измененных навигацией.Один из элементов управления запускает задачи.Я делаю это так:

public partial class uc_WorkingArea : UserControl
{
    CancellationTokenSource cts = new CancellationTokenSource();
    CancellationToken token;

    public uc_WorkingArea()
        {
            InitializeComponent();
            this.Unloaded += uc_WorkingArea_Unloaded;
            token = cts.Token;
            Task Printer1 = Task.Run(() => PrinterPooler(lst_PrinterStruct, 0), cts.Token);
        }


         private void uc_WorkingArea_Unloaded(object sender, RoutedEventArgs e)
        {
            cts.Cancel();
            if (token.CanBeCanceled)
            {
                MessageBox.Show("Can be canceled");
            }

            if (token.IsCancellationRequested)
            {
                MessageBox.Show("Canceled requested");
            }
            cts.Cancel();
            MessageBox.Show("Status: " + Printer1.Status.ToString());
        }
}

Когда я покидаю текущий пользовательский контроль и выполняю переключение на другое uc_WorkingArea_Unloaded.Я вижу сообщения, что Задача может быть отменена, и запрос на отмену принят.

Но, текущий статус задачи Printer1 по-прежнему "IsRunning".Итак, если я вернусь обратно к этому пользовательскому элементу управления, Задача запустится снова, и в Приложении будут запущены две похожие задачи.

Я попытался запустить задачу под Factory, как это

Task Printer1 = Task.Factory.StartNew(() => PrinterPooler(lst_PrinterStruct, 0), cts.Token);

Но безуспешно.Приложение по-прежнему выполняет две похожие задачи.

Метод PrinterPooler не асинхронный.

Я не могу понять, где была допущена ошибка.Ваша помощь, ребята, нужна.

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Относительно этого поста Как мне прервать / отменить Задачи TPL?

Вы должны самостоятельно реализовать свое состояние cancle.Например:

public partial class uc_WorkingArea : UserControl
{
    public CancellationTokenSource cts = new CancellationTokenSource();
    public CancellationToken token;
    public Task Printer1;

    public uc_WorkingArea()
    {
        token = cts.Token;
        Printer1 = Task.Factory.StartNew(() =>
        {
            while (!token.IsCancellationRequested)
            {
                Console.WriteLine("run");
                Application.DoEvents();
            }
        }, token);
    }
}

Отмена вызова:

    uc_WorkingArea gc = new uc_WorkingArea();

    for (int i = 0; i < 10; i++) //PASS SOME TIME
    {
        Application.DoEvents(); //CONSOLE SHOULD SPAM 'RUN' FROM TASK
        Thread.Sleep(1);
    }

    gc.cts.Cancel(); //CANCEL CALL, WHILE LOOP END
    if (gc.token.IsCancellationRequested)
    {
        Console.WriteLine("stop");
        MessageBox.Show("Canceled requested");

    }
    gc.cts.Dispose();
    gc.Printer1.Dispose();

Надеюсь, это поможет.

1 голос
/ 04 апреля 2019

Вы должны передать токен в метод PrintPooler и там внутри проверить, должен ли он быть отменен.

for(int i = 0; i < 10000; i++)
{
   DoStuff();
   cancelToken.ThrowIfCancellationRequested(); // if tasks end with this exception, it knows the work has been cancelled
}

Отмена задачи не останавливает выполнение, она только сигнализирует внутреннему коду о том, что она должна завершиться, и задает состояние задачи как Отменено / Сбой / RanToCompletion в зависимости от того, как выполнение останавливается.

Обратите внимание, что вам нужно передать один и тот же токен Задаче и методу, который его выбросит.

...