如何在 C# 4.0 中让任务进入睡眠(或延迟)状态?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15341962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 16:29:16  来源:igfitidea点击:

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

c#.netmultithreadingparallel-processingtask-parallel-library

提问by Fulproof

There is Task.Delayin .NET 4.5

.NET 4.5 中 有Task.Delay

How can I do the same in .NET 4.0?

我如何在 .NET 4.0 中做同样的事情?

采纳答案by Servy

You can use a Timerto create a Delaymethod in 4.0:

您可以使用 a在 4.0 中Timer创建Delay方法:

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

回答by QrystaL

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

如何在 4.0 中实现 Task.Delay部分

回答by DVD

You can download the Visual Studio Async CTPand use TaskEx.Delay

您可以下载Visual Studio Async CTP并使用 TaskEx.Delay

回答by Eli Arbel

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

使用来自 NuGet的Microsoft.Bcl.Async包,它具有TaskEx.Delay.

回答by Gusdor

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

下面是可取消 Task.Delay 实现的代码和示例工具。您可能对该Delay方法感兴趣。:

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

回答by f.capet

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

在许多情况下,纯粹的 AutoResetEvent 比 Thread.Sleep()...

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

hope that it helps

希望它有帮助

回答by WndRnr

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

回答by Edward Brey

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.AsyncNuGet package.

要在 .NET 4.0 上使用此代码,您需要Microsoft.Bcl.AsyncNuGet 包。

回答by Alex R.

Extending the idea from this answer:

扩展这个答案的想法:

new AutoResetEvent(false).WaitOne(1000);