How to put a task to sleep (or delay) in C# 4.0?

C#.NetMultithreadingParallel ProcessingTask Parallel-Library

C# Problem Overview


There is Task.Delay in .NET 4.5

How can I do the same in .NET 4.0?

C# Solutions


Solution 1 - C#

Use the Microsoft.Bcl.Async package from NuGet, it has TaskEx.Delay.

Solution 2 - C#

You can use a Timer to create a Delay method in 4.0:

public static Task Delay(double milliseconds)
{
    var tcs = new TaskCompletionSource<bool>();
    System.Timers.Timer timer = new System.Timers.Timer();
    timer.Elapsed+=(obj, args) =>
    {
        tcs.TrySetResult(true);
    };
    timer.Interval = milliseconds;
    timer.AutoReset = false;
    timer.Start();
    return tcs.Task;
}

Solution 3 - C#

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        Delay(2000).ContinueWith(_ => Console.WriteLine("Done"));
        Console.Read();
    }

    static Task Delay(int milliseconds)
    {
        var tcs = new TaskCompletionSource<object>();
        new Timer(_ => tcs.SetResult(null)).Change(milliseconds, -1);
        return tcs.Task;
    }
}

From the section How to implement Task.Delay in 4.0

Solution 4 - C#

Below is the code and sample harness for a cancellable Task.Delay implementation. You are likely interested in the Delay method.:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelayImplementation
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Threading.CancellationTokenSource tcs = new System.Threading.CancellationTokenSource();

            int id = 1;
            Console.WriteLine(string.Format("Starting new delay task {0}. This one will be cancelled.", id));
            Task delayTask = Delay(8000, tcs.Token);
            HandleTask(delayTask, id);

            System.Threading.Thread.Sleep(2000);
            tcs.Cancel();

            id = 2;
            System.Threading.CancellationTokenSource tcs2 = new System.Threading.CancellationTokenSource();
            Console.WriteLine(string.Format("Starting delay task {0}. This one will NOT be cancelled.", id));
            var delayTask2 = Delay(4000, tcs2.Token);
            HandleTask(delayTask2, id);

            System.Console.ReadLine();
        }

        private static void HandleTask(Task delayTask, int id)
        {
            delayTask.ContinueWith(p => Console.WriteLine(string.Format("Task {0} was cancelled.", id)), TaskContinuationOptions.OnlyOnCanceled);
            delayTask.ContinueWith(p => Console.WriteLine(string.Format("Task {0} was completed.", id)), TaskContinuationOptions.OnlyOnRanToCompletion);
        }

        static Task Delay(int delayTime, System.Threading.CancellationToken token)
        {
            TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();

            if (delayTime < 0) throw new ArgumentOutOfRangeException("Delay time cannot be under 0");

            System.Threading.Timer timer = null;
            timer = new System.Threading.Timer(p =>
            {
                timer.Dispose(); //stop the timer
                tcs.TrySetResult(null); //timer expired, attempt to move task to the completed state.
            }, null, delayTime, System.Threading.Timeout.Infinite);

            token.Register(() =>
                {
                    timer.Dispose(); //stop the timer
                    tcs.TrySetCanceled(); //attempt to mode task to canceled state
                });

            return tcs.Task;
        }
    }
}

Solution 5 - C#

Extending the idea from this answer:

new AutoResetEvent(false).WaitOne(1000);

Solution 6 - C#

You can download the Visual Studio Async CTP and use TaskEx.Delay

Solution 7 - C#

In many cases, a sheer AutoResetEvent is better than a Thread.Sleep()...

AutoResetEvent pause = new AutoResetEvent(false);
Task timeout = Task.Factory.StartNew(()=>{
pause.WaitOne(1000, true);
});

hope that it helps

Solution 8 - C#

    public static void DelayExecute(double delay, Action actionToExecute)
    {
        if (actionToExecute != null)
        {
            var timer = new DispatcherTimer
            {
                Interval = TimeSpan.FromMilliseconds(delay)
            };
            timer.Tick += (delegate
            {
                timer.Stop();
                actionToExecute();
            });
            timer.Start();
        }
    }

Solution 9 - C#

Here's a succinct, timer-based implementation with proper cleanup:

var wait = new TaskCompletionSource<bool>();
using (new Timer(_ => wait.SetResult(false), null, delay, Timeout.Infinite))
	await wait.Task;

To use this code on .NET 4.0, you need the Microsoft.Bcl.Async NuGet package.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFulproofView Question on Stackoverflow
Solution 1 - C#Eli ArbelView Answer on Stackoverflow
Solution 2 - C#ServyView Answer on Stackoverflow
Solution 3 - C#QrystaLView Answer on Stackoverflow
Solution 4 - C#GusdorView Answer on Stackoverflow
Solution 5 - C#Alex R.View Answer on Stackoverflow
Solution 6 - C#DVDView Answer on Stackoverflow
Solution 7 - C#f.capetView Answer on Stackoverflow
Solution 8 - C#WndRnrView Answer on Stackoverflow
Solution 9 - C#Edward BreyView Answer on Stackoverflow