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

Cli*_* Ok 8 c# task thread-safety async-await

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

// SAMPLE 01
Thread.Sleep(30 * 1000)
Run Code Online (Sandbox Code Playgroud)

但它有一个缺点,会阻塞当前线程。另一种选择

// SAMPLE 02
await Task.Delay(30 * 1000)
Run Code Online (Sandbox Code Playgroud)

仅适用于异步方法。但我需要在同步方法中使用它。我们不能这样做

// SAMPLE 03
Task.Delay(30 * 1000).Wait()
Run Code Online (Sandbox Code Playgroud)

因为它可能会导致僵局(至少我是这么认为)。我的最终解决方案是

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

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

额外问题:SAMPLE 03真的可以解决死锁问题吗?如果我们这样做怎么办:

// SAMPLE 05
Task.Delay(30 * 1000).Wait(30 * 1000)
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 8

此解决方案(示例 04)真的比示例 01(使用 Thread.Sleep)更好吗?

不,情况更糟。示例 01 更容易理解,也更高效。

它的缺点是会阻塞当前线程。

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

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

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

事实上,您的所有示例都会阻塞调用线程(02 除外,它是异步的)。Wait与调用线程一样阻塞调用线程Thread.Sleep

SAMPLE 03 真的可以做死锁吗?

不。为了产生僵局,你需要两个不同的事物互相等待才能继续。对于经典的同步异步死锁,你需要做的两件事是:

  1. 捕获单线程上下文async的方法。await
  2. 同一上下文中的线程被阻塞。

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