是否有很好的规则来说明何时使用Task。Delay vs . Thread.Sleep?
具体来说,是否存在一个最小值来保证其中一个比另一个更有效? 最后,自从任务。延迟导致异步/等待状态机上的上下文切换,是否有使用它的开销?
是否有很好的规则来说明何时使用Task。Delay vs . Thread.Sleep?
具体来说,是否存在一个最小值来保证其中一个比另一个更有效? 最后,自从任务。延迟导致异步/等待状态机上的上下文切换,是否有使用它的开销?
当前回答
任务之间最大的区别。延迟和线程。睡眠就是那个任务。Delay旨在异步运行。使用Task没有意义。同步代码中的延迟。使用线程是一个非常糟糕的主意。在异步代码中休眠。
通常你会用await关键字调用Task.Delay():
await Task.Delay(5000);
或者,如果你想在延迟之前运行一些代码:
var sw = new Stopwatch();
sw.Start();
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;
猜猜这会打印什么?运行0.0070048秒。 如果我们将await延迟移到控制台上方。而是写入eline,它将打印运行5.0020168秒。
让我们看看Thread的不同之处。睡眠:
class Program
{
static void Main(string[] args)
{
Task delay = asyncTask();
syncCode();
delay.Wait();
Console.ReadLine();
}
static async Task asyncTask()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine("async: Starting");
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine("async: Done");
}
static void syncCode()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine("sync: Starting");
Thread.Sleep(5000);
Console.WriteLine("sync: Running for {0} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine("sync: Done");
}
}
试着预测一下它会打印什么…
异步:开始 async:运行0.0070048秒 同步:开始 async:运行5.0119008秒 异步:完成 sync:运行5.0020168秒 同步:完成
另外,有趣的是注意到Thread。睡眠要精确得多,毫秒精度不是真正的问题,而任务。延迟最少需要15-30毫秒。与ms精度相比,这两个函数的开销是最小的(如果你需要更精确的东西,请使用Stopwatch Class)。线程。睡眠仍然束缚着你的线程,任务。在等待的同时,延迟释放它以做其他工作。
其他回答
我的观点,
Task.Delay()是异步的。它不会阻塞当前线程。您仍然可以在当前线程中执行其他操作。它返回一个Task返回类型(Thread.Sleep()不返回任何东西)。您可以检查该任务是否已完成(使用task。IsCompleted属性),稍后在另一个耗时的过程之后。
Thread.Sleep()没有返回类型。它是同步的。在线程中,除了等待延迟完成之外,您实际上不能做任何事情。
至于在现实生活中的使用,我已经编程15年了。我从未在产品代码中使用过Thread.Sleep()。我找不到任何用例。 也许是因为我主要从事web应用程序开发。
我想补充一点。 实际上,任务。Delay是一种基于定时器的等待机制。如果您查看源代码,您会发现一个Timer类的引用,它是造成延迟的原因。另一方面,线程。Sleep实际上使当前线程休眠,这样你只是阻塞和浪费了一个线程。在异步编程模型中,如果你想在延迟后发生某些事情(延续),你应该总是使用Task.Delay()。
任务之间最大的区别。延迟和线程。睡眠就是那个任务。Delay旨在异步运行。使用Task没有意义。同步代码中的延迟。使用线程是一个非常糟糕的主意。在异步代码中休眠。
通常你会用await关键字调用Task.Delay():
await Task.Delay(5000);
或者,如果你想在延迟之前运行一些代码:
var sw = new Stopwatch();
sw.Start();
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;
猜猜这会打印什么?运行0.0070048秒。 如果我们将await延迟移到控制台上方。而是写入eline,它将打印运行5.0020168秒。
让我们看看Thread的不同之处。睡眠:
class Program
{
static void Main(string[] args)
{
Task delay = asyncTask();
syncCode();
delay.Wait();
Console.ReadLine();
}
static async Task asyncTask()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine("async: Starting");
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine("async: Done");
}
static void syncCode()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine("sync: Starting");
Thread.Sleep(5000);
Console.WriteLine("sync: Running for {0} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine("sync: Done");
}
}
试着预测一下它会打印什么…
异步:开始 async:运行0.0070048秒 同步:开始 async:运行5.0119008秒 异步:完成 sync:运行5.0020168秒 同步:完成
另外,有趣的是注意到Thread。睡眠要精确得多,毫秒精度不是真正的问题,而任务。延迟最少需要15-30毫秒。与ms精度相比,这两个函数的开销是最小的(如果你需要更精确的东西,请使用Stopwatch Class)。线程。睡眠仍然束缚着你的线程,任务。在等待的同时,延迟释放它以做其他工作。
如果当前线程被杀死,你使用thread。Sleep并且它正在执行,那么你可能会得到一个ThreadAbortException。 与任务。延迟您总是可以提供一个取消令牌并优雅地终止它。这就是我选择Task.Delay的原因之一。参见http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx
我也同意在这种情况下效率不是最重要的。
使用线程。当您想要阻塞当前线程时休眠。
使用await Task。延迟:当您希望在不阻塞当前线程的情况下进行逻辑延迟时。
效率不应该是这些方法的首要考虑因素。它们在现实世界中的主要用途是作为I/O操作的重试计时器,其数量级为秒而不是毫秒。