2013-07-11 6 views
2

У меня есть службы Windows, который запускает задачу при запускекак отменить задачу быстрее

Эта задача, которая имеет время цикла и после выполнения одной итерации это пойти спать в течение 5 минут.

Когда я останавливаю обслуживание, задача отмены первой и позже некоторые другие операции получают выполняются

если задача находится в режиме сна, он отменен только тогда, когда он просыпается, я хочу, чтобы это было отменено, даже если он спит и не хочет дождаться его пробуждения.

Ниже приведен код

Task controllerTask = Task.Factory.StartNew(() => 
{ 
    var interval = 300; 
    while(true) 
    { 
     if (cancellationToken.IsCancellationRequested) 
      break; 
     Thread.Sleep(interval * 1000); 
     if (cancellationToken.IsCancellationRequested) 
      break; 
     //SOME WORK HERE 
    } 
}, cancellationToken); 

Есть ли способ?

EDIT: Я не могу использовать Task.Delay, я не могу найти его в System.Threading.Tasks.Task пространстве имен, потому что я использую .NET Framework 4.0 не 4,5

Есть ли другое лучшее решение, которое работает с 4.0.

ответ

2

Это одно решение для блокировки, которое вы можете использовать в C# 4.0, VS2010.

cancellationToken.WaitHandle.WaitOne(TimeSpan.FromMinutes(5)); 

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

+0

Он отлично поработал –

0

Я сломал длинный сон на несколько небольших спальных места, следующее модифицированный код:

Task controllerTask = Task.Factory.StartNew(() => 
{ 
while(true) 
{ 
    if (cancellationToken.IsCancellationRequested) break; 
    var sleepTime = 10; 
    if (interval < sleepTime) 
     interval = sleepTime; 

    var iteration = (interval/sleepTime); 
    if ((interval % sleepTime) > 0) 
     iteration++; 
    bool cancel = false; 
    for (int i = 0; i < iteration; i++) 
    { 
     Thread.Sleep(sleepTime * 1000); 
     if (cancellationToken.IsCancellationRequested) { cancel = true; break; }; 
    } 
    if (cancel) break; 

    //SOME WORK HERE 
} 
} 
+3

Я бы порекомендовал вам принять лучшее решение с помощью cancelationToken. Этот метод представляет собой расточительствование циклов. – Petesh

11

Использование Task.Delay вместо Thread.Sleep. Он принимает параметр CancellationToken, поэтому вы можете прервать его до конца задержки.

Если вы используете код асинхронного, вы могли бы написать это следующим образом:

await Task.Delay(duration, cancellationToken); 

Если это синхронный код, вы можете просто ждать задачу:

Task.Delay(duration, cancellationToken).Wait(); 
+1

Это также имеет то преимущество, что он не связывает поток потока нити в течение 5 минут (в первом асинхронном случае.) –

+0

@DanBryant Вы говорите, что 'await' не связывает его и' .Wait () 'делает? Или просто, что OPs привязал его. – weston

+0

@ Томас, можете ли вы написать решение по моему коду, где поставить эту строку? вместо Thread.Sleep? –

2

Вдохновленной других ответы , простой пример использования ждут этой проблемы:

public static class TaskExtension 
{ 
    /// <summary> 
    /// Call to highlight fact that you do not want to wait on this task. 
    /// 
    /// This nicely removes resharper warnings without need for comments. 
    /// </summary> 
    /// <param name="task"></param> 
    public static void FireAndForget(this Task task) 
    { 
    } 
} 

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     var cancellationToken = new CancellationTokenSource(); 
     TaskCode(cancellationToken.Token).FireAndForget(); 
     Console.ReadLine(); 
     cancellationToken.Cancel(); 
     Console.WriteLine("End"); 
     Console.ReadLine(); 
    } 

    private static async Task TaskCode(CancellationToken cancellationToken) 
    { 
     while (!cancellationToken.IsCancellationRequested) 
     { 
      var interval = TimeSpan.FromSeconds(1); 
      await Task.Delay(interval, cancellationToken); 

      //SOME WORK HERE 
      Console.WriteLine("Tick"); 
     } 
    } 
} 
+0

Я бы рекомендовал вернуть TaskCode Task вместо void. Возврат void действительно предназначен только для обратной совместимости, поэтому делегаты обработчика событий могут быть сделаны асинхронными без изменения их возвращаемого значения. Также неплохо позволить Распространению TaskCanceledException распространяться, а не изменять его в пустой «возврат», так как в последней задаче будет корректно указано состояние «Отменено». –

+0

На самом деле вам не нужно использовать Task.StartNew, потому что TaskCode вернется к вызывающему, когда встретится первый 'await'. Затем он возобновит выполнение в конце 'Delay'. Кстати, вы не должны передавать «CancellationTokenSource», просто «CancellationToken». –

+0

Спасибо за ваш ответ @weston, но я не могу использовать Task.Delay, я не могу найти его в пространстве имен System.Threading.Tasks.Task, потому что я использую .Net Framework 4.0 не 4.5 –

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