Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A task that will never end until cancellation is requested

I need a task that never ends until cancellation is requested. At the moment the simplest way to do that is:

var cancellation = new CancellationTokenSource();

var task = Task.Factory.StartNew(async () =>
{
    while (true)
    {
        await Task.Delay(10000, cancellation.Token);
    }
}, cancellation.Token).Unwrap();

What I don't like is a call to Task.Delay method because it requires limited time interval for waiting.

Is there more elegant solution?

like image 342
neleus Avatar asked May 03 '14 15:05

neleus


People also ask

What is task Cancelled exception?

TaskCanceledException(String, Exception, CancellationToken) Initializes a new instance of the TaskCanceledException class with a specified error message, a reference to the inner exception that is the cause of this exception, and the CancellationToken that triggered the cancellation.

What is the way to create a task that can be Cancelled after it starts?

Create and start a cancelable task. Pass a cancellation token to your user delegate and optionally to the task instance. Notice and respond to the cancellation request in your user delegate. Optionally notice on the calling thread that the task was canceled.

How do you cancel asynchronous tasks?

You can cancel an asynchronous operation after a period of time by using the CancellationTokenSource. CancelAfter method if you don't want to wait for the operation to finish.

Which of the following options should be used to implement cancellation for a long running task?

Here is the sample code to cancel a task, CancellationTokenSource mCancellationTokenSource = new CancellationTokenSource(); CancellationToken token = mCancellationTokenSource.


2 Answers

You should be able to subscribe to the cancellation of the token and complete the task then:

public static Task UntilCancelled(CancellationToken tok)
{
    var tcs = new TaskCompletionSource<object>();
    IDisposable subscription = null;
    subscription = tok.Register(() =>
    {
        tcs.SetResult(null);
        subscription.Dispose();
    });

    return tcs.Task;
}
like image 37
Lee Avatar answered Oct 14 '22 08:10

Lee


As an alternative to TaskCompletionSource with token.Register, here are some one-liners:

var task = new Task(() => {}, token); // don't do task.Run()!

Or, simply this:

var task = Task.Delay(Timeout.Infinite, token);

There's even a nice optimization for Timeout.Infinite in the current Task.Delay implementation.

like image 83
noseratio Avatar answered Oct 14 '22 07:10

noseratio