how to cancel Task quicker

放肆的年华 提交于 2020-01-04 13:43:36

问题


I have a Windows Service which starts a task on start up

This task which has a while loop and after performing one iteration it go to sleep for 5 minutes.

When I stop service, the task is cancelled first and later some other operations gets performed

if the task is in sleep, it get cancelled only when it wakes up , i want it to be cancelled even if it is sleeping and don't want to wait for waking it up.

following is the code

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

Is there any way?

EDIT: I am not able to use Task.Delay , I can't find it in System.Threading.Tasks.Task namespace , because I am using .Net Framework 4.0 not 4.5

Is there any other better solution that works with 4.0.


回答1:


This is one blocking solution you can use in C# 4.0, VS2010.

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

It will unblock when you cancel the token source or on timeout which is your desired sleep interval.




回答2:


Use Task.Delay instead of Thread.Sleep. It takes a CancellationToken parameter so you can abort it before the end of the delay.

If you're using async code, you could write it like this:

await Task.Delay(duration, cancellationToken);

If it's synchronous code, you can just wait the task:

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



回答3:


Inspired by the other answers, simple example of using await for this problem:

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



回答4:


I've broken long sleep into multiple small sleeps, following is the modified code:

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


来源:https://stackoverflow.com/questions/17597642/how-to-cancel-task-quicker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!