C# 中的 Thread.Sleep()

Haider Ali 2023年10月12日
  1. 为什么 thread.sleep()C# 中是有害的
  2. thread.sleep() 如何在 C# 中工作
  3. 异步编程
  4. 同时运行两个方法(C# 中的 asyncawait 关键字)
C# 中的 Thread.Sleep()

在本指南中,我们将了解为什么在 C# 中使用 thread.sleep() 被认为是有害的,以及为什么不应该使用这种特殊方法。

使用 thread.sleep() 会发生什么?有没有替代方法?

找出本指南中的所有内容。让我们深入了解一下。

为什么 thread.sleep()C# 中是有害的

要理解 thread.sleep() 为何有害,我们必须了解此方法背后的工作。好吧,在 C# 中,sleep 方法有其用途。

你可以使用它在特定时间段内暂停或暂停当前功能(线程执行)。我们可以通过以毫秒为单位的时间来暂停线程执行一段时间。

我们还可以使用 TimeSpan 属性,如下面的代码所示。

// Time in milliseconds
Thread.Sleep(5000);
Or
    // Time in hours, minutes, seconds
    TimeSpan tsObj = new TimeSpan(0, 0, 5);
Thread.Sleep(tsObj);

现在,上述两种方法都会停止程序五秒钟。这意味着,通过上面的代码,我们试图将线程挂起 1 秒。

但是,这一切的意义何在?让我们了解它的工作原理。

thread.sleep() 如何在 C# 中工作

我们都知道一个程序逐行运行,这意味着整个程序同步运行,一行接一行。有时,在编程过程中,我们需要执行一项需要一些时间才能完成的任务。

例如,从 API 获取数据,我们可以使用 sleep 函数让它等待,从 API 获取数据,然后运行程序的其余部分。这是必要的,但却是一种非常有害和糟糕的方法。

例如,我们试图获取的数据可能很大并且需要时间。我们的程序将在此期间停止;这不是一个理想的方法。

Thread.Sleep(n) 意味着在 n 毫秒内尽可能多的时间片(也称为线程量子)停止正在运行的线程。时间片的持续时间取决于 Windows 的版本/类型和使用的处理器,但通常持续 15 到 30 毫秒。

这表明线程可能会阻塞超过 n 毫秒。你的线程不太可能在 n 毫秒后精确地重新唤醒。

因此,Thread.Sleep 在计时方面没有任何作用。

线程是一种有限资源,需要大约 200,000 次循环创建和 100,000 次循环销毁。默认情况下,他们为每个上下文转换使用 2,000–8,000 个周期,并为他们的堆栈保留 1 兆字节的虚拟内存。

什么是替代方法

我们有时需要延迟我们的线程以使程序完美运行。如上所述,我们可能需要获取一些 API 数据,这需要时间。

但是因为它而停止整个程序是一种不好的方法。那么,我们该如何避免呢?

让我们向你介绍异步编程。

异步编程

C# 中的 asyncawait 关键字有助于使异步编程在当今变得非常普遍。整个应用程序在使用 UI 时将不得不等待完成操作并使用需要很长时间的长时间运行的方法,例如读取一个巨大的文件或单击一个按钮。

换句话说,如果同步应用程序中的任何进程被阻塞,整个应用程序也会停止,我们的应用程序将停止运行,直到整个任务完成。

在这种情况下,异步编程非常有用。通过采用异步编程,应用程序可以继续执行不依赖于完成的任务。

借助 asyncawait 关键字,我们将以更少的工作实现传统异步编程的所有优点。

同时运行两个方法(C# 中的 asyncawait 关键字)

假设我们有两个方法,FirstMethod()SecondMethod(),它们彼此独立,并且 FirstMethod() 需要很长时间才能执行其任务。

同步编程从 FirstMethod() 开始并等待它完成,然后再继续执行 SecondMethod()。即使这两个过程是独立的,这个过程也会花费很多时间。

我们可以通过使用简单的线程编程同时运行所有功能,但这会在我们等待任务完成时阻塞用户界面。在传统的编程中,我们需要编写大量的代码来解决这个问题,但是如果我们使用 asyncawait 关键字,我们可以用更少的代码解决这个问题。

我们还将看到其他示例,在这些情况下,当 SecondMethod() 依赖于 FirstMethod() 时,它将使用 await 关键字等待 FirstMethod() 完成运行。

在 C# 中,asyncawait 是代码标记,用于指示当任务完成时控件应返回的位置。

从真实世界的示例开始将帮助你更好地理解它们背后的编程。看看下面的代码。

class Program {
  static void Main(string[] args) {
    FirstMethod();
    SecondMethod();
    Console.ReadKey();
  }

  public static async Task FirstMethod() {
    await Task.Run(() => {
      for (int i = 0; i < 100; i++) {
        Console.WriteLine(" First Method");
        // Do something
        Task.Delay(100).Wait();
      }
    });
  }

  public static void SecondMethod() {
    for (int i = 0; i < 25; i++) {
      Console.WriteLine(" Second Method ");
      // Do something
      Task.Delay(100).Wait();
    }
  }
}

上述代码的输出将如下所示。

First Method
Second Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
Second Method
Second Method
Second Method
Second Method

正如你在上面的代码中看到的那样,整个程序不会因为我们必须停止执行一个线程而停止。它们都可以使用异步编程同时运行。

假设你在某个时刻必须获取一些 API 数据,这需要时间。因此,程序将在没有获取数据的情况下移动到下一行,因此我们需要稍微延迟一下以获取该数据,然后再移动到下一行。

作者: Haider Ali
Haider Ali avatar Haider Ali avatar

Haider specializes in technical writing. He has a solid background in computer science that allows him to create engaging, original, and compelling technical tutorials. In his free time, he enjoys adding new skills to his repertoire and watching Netflix.

LinkedIn

相关文章 - Csharp Thread