C# - 多线程:初学者指南

你好,未来的C#开发者们!今天,我们将踏上一段激动人心的旅程,探索多线程的世界。别担心,这可能听起来有点吓人——但我将是你的友好向导,我们会一步一步来。在本教程结束时,你将能够像专业人士一样进行线程操作!

C# - Multithreading

什么是多线程?

在我们深入之前,让我们先了解一下什么是多线程。想象你正在烹饪一顿复杂的饭菜。你不会一次只做一个任务,对吧?你可能一边在炉子上煮意大利面,一边切菜,还要留意酱汁。这就是多任务处理,在编程的世界里,我们称之为多线程。

多线程允许程序同时执行多个任务。这就好比厨房里有多个厨师,每个人负责饭菜的不同部分。

线程生命周期

就像我们人类一样,线程也有生命周期。让我们来分解一下:

  1. 诞生(新建):线程已创建但尚未启动。
  2. 就绪:线程准备好运行,等待CPU时间。
  3. 运行:线程正在执行其任务。
  4. 阻塞:线程暂时暂停(可能正在等待某些资源)。
  5. 死亡:线程已完成其任务,不再运行。

下面是一个简单的可视化:

新建 -> 就绪 -> 运行 -> 死亡
^        |
|        v
<-- 阻塞

主线程

当你启动一个C#程序时,它自动创建了一个名为主线程的线程。就像我们厨房比喻中的主厨。让我们看看它是如何工作的:

using System;
using System.Threading;

class Program
{
static void Main(string[] args)
{
Console.WriteLine("主线程: " + Thread.CurrentThread.ManagedThreadId);
}
}

当你运行这个程序时,你将看到类似以下内容:

主线程: 1

这表明我们的程序正在主线程上运行,其线程ID始终为1。

Thread类的属性和方法

C#中的Thread类带有一系列有用的属性和方法。让我们来看看一些最常用的:

属性/方法 描述
ManagedThreadId 获取线程的唯一标识符
IsAlive 指示线程是否已启动且尚未终止
Name 获取或设置线程的名称
Priority 获取或设置线程的调度优先级
Start() 启动线程
Sleep() 指定时间暂停线程
Join() 阻塞调用线程,直到此线程终止

让我们看看其中一些是如何工作的:

using System;
using System.Threading;

class Program
{
static void Main(string[] args)
{
Thread t = new Thread(DoWork);
t.Name = "工作线程";
Console.WriteLine("启动线程...");
t.Start();
t.Join();
Console.WriteLine("线程结束");
}

static void DoWork()
{
Console.WriteLine($"线程 {Thread.CurrentThread.Name} 正在工作");
Thread.Sleep(1000);
Console.WriteLine($"线程 {Thread.CurrentThread.Name} 完成工作");
}
}

这个程序创建了一个新线程,命名它,启动它,等待它完成,然后继续。输出将是:

启动线程...
线程 工作线程 正在工作
线程 工作线程 完成工作
线程结束

创建线程

在C#中创建线程就像是为我们的厨房雇佣新厨师。以下是如何操作的:

using System;
using System.Threading;

class Program
{
static void Main(string[] args)
{
// 使用命名方法创建线程
Thread t1 = new Thread(DoWork);
t1.Start();

// 使用匿名方法创建线程
Thread t2 = new Thread(() =>
{
Console.WriteLine("线程 2 正在工作");
});
t2.Start();

// 使用参数创建线程
Thread t3 = new Thread(param =>
{
Console.WriteLine($"线程 3 说:{param}");
});
t3.Start("来自线程 3 的问候!");
}

static void DoWork()
{
Console.WriteLine("线程 1 正在工作");
}
}

这个例子展示了创建线程的三种不同方法。运行它,看看会发生什么!

管理线程

管理线程对于有效的多线程至关重要。让我们看看一些管理方法:

using System;
using System.Threading;

class Program
{
static void Main(string[] args)
{
Thread t = new Thread(DoWork);
t.Start();

// 等待线程结束
t.Join();

// 设置线程优先级
t.Priority = ThreadPriority.Highest;

// 检查线程是否存活
Console.WriteLine($"线程是否存活? {t.IsAlive}");

// 主线程暂停
Thread.Sleep(1000);
}

static void DoWork()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"工作... {i}");
Thread.Sleep(500);
}
}
}

这个示例演示了如何等待线程结束、设置其优先级、检查其状态以及使线程暂停。

销毁线程

在C#中,我们通常不会手动“销毁”线程。线程在完成工作或应用程序退出时自动终止。然而,我们可以使用Abort()方法请求线程停止,尽管由于潜在的清理问题,通常不推荐这样做。

下面是如何使用Abort()的示例,但记住,最好设计线程自然完成:

using System;
using System.Threading;

class Program
{
static void Main(string[] args)
{
Thread t = new Thread(DoWork);
t.Start();

Thread.Sleep(2000); // 让线程运行2秒

t.Abort(); // 终止线程
Console.WriteLine("线程已终止");
}

static void DoWork()
{
while (true)
{
Console.WriteLine("工作...");
Thread.Sleep(500);
}
}
}

这将运行线程大约2秒后终止它。

就这样!你刚刚完成了C#多线程的第一个教程。记住,就像学做饭一样,掌握多线程需要练习。所以不要害怕尝试这些概念。快乐编码,愿你的线程总是运行顺利!

Credits: Image by storyset