Как отменить запущенное задание? - PullRequest
0 голосов
/ 08 мая 2018

Я хочу отменить запущенное задание (когда пользователь нажимает клавишу выхода). когда я нажимаю на клавишу «escape», запускается Form_KeyDown, но не отменяет задачу!

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token=new CancellationToken();

private async void Search_Button_ClickAsync(object sender, EventArgs e)
{
  token = tokenSource.Token;
  await (Task.Factory.StartNew(() =>
           {
             //...my program
           },
           token));

private void Form_KeyDown(object sender, KeyEventArgs e)
{
  if (e.KeyCode == Keys.Escape)
  {
    tokenSource.Cancel();
  }
}

1 Ответ

0 голосов
/ 08 мая 2018

Вы делаете все хорошо, за исключением того факта, что вам нужно остановить выполнение кода внутри вашего метода. Передав токен отмены в Task.Factory.StartNew, вы не отменяете задачу. Позвольте мне процитировать Stephen Toub:

Передача токена в StartNew связывает токен с заданием. Это имеет два основных преимущества: 1) Если токен имеет отмену запрошенный до начала выполнения задачи, задача не будет выполнить. Вместо того, чтобы перейти на бег, он сразу Переход на Отменен. Это позволяет избежать затрат на выполнение задачи, если все равно было бы отменено во время работы. 2) Если тело Задача также отслеживает токен отмены и выдает OperationCanceledException, содержащая этот токен ThrowIfCancellationRequested делает), затем, когда задача видит, что OCE, он проверяет, совпадает ли токен OCE с токеном Задачи. Если оно делает это исключение рассматривается как признание кооператива Отмена и Задача переходит в состояние Отменено (скорее чем неисправное состояние).

Вам нужно вручную проверить, был ли отменен ваш токен, и исключить исключение из операции выброса, что-то вроде этого:

 private async void Search_Button_ClickAsync(object sender, EventArgs e)
    {
      cToken = cTokenSource.Token;
      await (Task.Factory.StartNew(() =>
               {

               for(int i=0;i<yourtaskcount;i++)
               { 
                 cToken.ThrowIfCancellationRequested();

                  //long work
               cToken));
    }
    private void Form_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Escape)
      {
        tokenSource.Cancel();
      }
    }
...