簡體   English   中英

如何更快地取消任務

[英]how to cancel Task quicker

我有一個Windows服務,它啟動時啟動任務

這個任務有一個while循環,在執行一次迭代后,它會進入睡眠狀態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);

有什么辦法嗎?

編輯:我無法使用Task.Delay,我在System.Threading.Tasks.Task命名空間中找不到它,因為我使用的是.Net Framework 4.0而不是4.5

有沒有其他更好的解決方案適用於4.0。

使用Task.Delay而不是Thread.Sleep 它需要一個CancellationToken參數,因此您可以在延遲結束之前中止它。

如果您使用的是異步代碼,可以這樣寫:

await Task.Delay(duration, cancellationToken);

如果它是同步代碼,您可以等待任務:

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

受其他答案啟發,使用等待此問題的簡單示例:

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");
        }
    }
}

這是一個可以在C#4.0,VS2010中使用的阻止解決方案。

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

當您取消令牌源或超時(即所需的睡眠間隔)時,它將取消阻止。

我已經將長時間睡眠分成多個小睡眠,以下是修改后的代碼:

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
 }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM