Task.Delay或Thread.Sleep在同步方法中暂停执行

时间:2019-05-20 23:10:58

标签: c# async-await thread-safety task

我想暂停同步方法。我知道我可以使用:

// SAMPLE 01
Thread.Sleep(30 * 1000)

,但是它有阻塞当前线程的缺点。替代

// SAMPLE 02
await Task.Delay(30 * 1000)

仅适用于异步方法。但是我需要通过 sync 方法来实现。我们不能这样做

// SAMPLE 03
Task.Delay(30 * 1000).Wait()

因为它可能导致死锁(至少我认为是这样)。我的最终解决方案是

// SAMPLE 04
Task.Run(() => Task.Delay(30 * 1000)).Wait();

最后,我的问题是:这个解决方案( SAMPLE 04 )确实比 SAMPLE 01 (使用Thread.Sleep)好吗?

奖金问题:示例03 真的可以造成僵局吗?如果我们这样做:

// SAMPLE 05
Task.Delay(30 * 1000).Wait(30 * 1000)

1 个答案:

答案 0 :(得分:2)

  

此解决方案(SAMPLE 04)确实比SAMPLE 01(使用Thread.Sleep)更好吗?

不。更糟样本01既易于理解,也更有效。

  

它有一个阻塞当前线程的缺点。

Thread.Sleep确实阻塞了当前线程。在异步方法中,这将是一个缺点。

  

我需要在同步方法中使用它。

然后,根据定义,您想要阻止当前线程。这就是同步的意思。

实际上,您的所有示例 do 都会阻止调用线程(02除外,后者是异步的)。 WaitThread.Sleep一样阻塞调用线程。

  

示例03真的可以造成死锁吗?

不。为了陷入僵局,您需要先等待两个不同的事物,然后它们才能继续。对于classical sync-over-async deadlock,您的两件事是:

  1. 一个async的{​​{1}}捕获了单线程上下文的方法。
  2. 在同一上下文中被阻塞的线程。

在您的示例中,您有一个线程被阻止。假设有一个单线程上下文,并且该线程在该上下文中被阻塞。您仍然不会遇到死锁,因为await方法无法捕获其上下文。这样就不会出现僵局。