2014-01-15 4 views
3

Я начинаю несколько тестов об асинхронной программировании в .net, и теперь я застреваю при попытке отменить длительную операцию с помощью cancelationToken.Асинхронное отключение во время работы

Поэтому у меня есть следующий код:

CancellationTokenSource cancelationToken = new CancellationTokenSource(); 

Мои кнопки для запуска операции

private void button2_Click(object sender, EventArgs e) 
    { 
     cancelationToken.Cancel(true); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     StartOperation(cancelationToken.Token); 
    } 

И, наконец, мои операции

private async void StartOperation(CancellationToken cancelToken) 
    { 
     await GetItensFromDatabase2(cancelToken); 
    } 

    public static Task<int> GetItensFromDatabase(CancellationToken cancelToken) 
    { 
     //cancelToken.Register(() => Console.WriteLine("Canceled")); 
     return Task.Factory.StartNew<int>(() => 
     { 
      int result = 0; 

      cancelToken.ThrowIfCancellationRequested(); 

      result = MyLongOperation(); // Simulates my operation -> I want to cancel while this operation is still running 

      return result; 

     }, cancelToken); 
    } 

Итак, как отменить MyLongOperation() метод? Можно ли это сделать?

+0

Используйте 'Task.Run' вместо' StartNew' для 'async' кода; [Я объясняю, почему в моем блоге] (http://blog.stephencleary.com/2013/08/startnew-is-dangerous.html). –

+0

Task.Run не существует в .net 4 – mmarques

+0

В 'Microsoft.Bcl.Async' это' TaskEx.Run'. –

ответ

5

Это невозможно отменить в любой момент, цель CancellationToken, чтобы позволить пользователю отменить операцию, когда длинная операция работает ожидать, что ...

while(!finished) 
{ 
    cancelToken.ThrowIfCancellationRequested(); 
    //Some not cancelable operations 
} 

Вот более распространенный метод отменяемый метод

private static void LongRunning(CancellationToken cancelToken) 
{ 
    while (true) 
    { 
     if(cancelToken.IsCancellationRequested) 
     { 
      return; 
     } 
     //Not canceled, continue to work 
    } 
} 

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

Нехорошо экспериментировать с Abort долгие операции без запроса оппонента, об этом написано много сообщений.

+0

Что вы говорите, что я могу только отменить операции внутри цикла? , и если моя текущая точка выполнения находится за пределами if (cancelToken.IsCancellationRequested), и пользователь хочет отменить, поэтому отмена в данный момент не разрешена? – mmarques

+0

Вы можете запустить цикл linear, некоторый код, чем if (cancelToken.IsCancellationRequested) return; чем другой код, чем снова проверить на отмену и ... –

1

Для начала у вас возникнет проблема, если вы уже прошли через логику, которая говорит «cancelToken.ThrowIfCancellationRequested», а затем вы отменяете. Как «MyLongOperation» знает, что вы отменили задание? :)

Отмена долго выполняющиеся задачи, как правило, занимает в CancellationToken в качестве аргумента, так что код будет выглядеть примерно так:

// Check if cancelled 
// do work part 1 
// Check if cancelled 
// do work part 2 

зернистость расторжение операций ДО разработчика.

+0

Это apraach, которого я боюсь. благодаря – mmarques

Смежные вопросы