C# 创建线程的方式
在C#里,创建线程有多种方式,下面为你详细介绍并给出示例。
1. 使用Thread类
通过Thread
类创建线程是最基础的方式,有两种途径可以启动线程:
- 使用ThreadStart委托:这种方式适用于线程执行的方法没有返回值(即返回类型为
void
)。 - 使用ParameterizedThreadStart委托:当线程执行的方法需要参数时,可以使用这种方式。
下面是具体的示例代码:
using System;
using System.Threading;class Program
{static void Main(){// 使用ThreadStart委托Thread thread1 = new Thread(PrintNumbers);thread1.Start();// 使用ParameterizedThreadStart委托Thread thread2 = new Thread(PrintNumbersWithDelay);thread2.Start(500); // 传递毫秒级延迟作为参数Console.WriteLine("主线程继续执行...");Console.ReadLine();}static void PrintNumbers(){for (int i = 1; i <= 5; i++){Console.WriteLine($"线程1: {i}");Thread.Sleep(100);}}static void PrintNumbersWithDelay(object delay){int ms = (int)delay;for (int i = 1; i <= 5; i++){Console.WriteLine($"线程2: {i}");Thread.Sleep(ms);}}
}
2. 使用ThreadPool
线程池能够管理和复用线程,从而减少线程创建和销毁所带来的开销。你可以使用QueueUserWorkItem
方法将工作项加入线程池队列。
using System;
using System.Threading;class Program
{static void Main(){// 将方法排入线程池队列执行ThreadPool.QueueUserWorkItem(PrintNumbers);ThreadPool.QueueUserWorkItem(PrintNumbersWithDelay, 300);Console.WriteLine("主线程继续执行...");Console.ReadLine();}static void PrintNumbers(object state){for (int i = 1; i <= 5; i++){Console.WriteLine($"线程池线程: {i}");Thread.Sleep(100);}}static void PrintNumbersWithDelay(object delay){int ms = (int)delay;for (int i = 1; i <= 5; i++){Console.WriteLine($"带延迟的线程池线程: {i}");Thread.Sleep(ms);}}
}
3. 使用Task Parallel Library (TPL)
借助Task
类可以创建和管理异步操作,这是.NET 4.0引入的特性,推荐优先使用这种方式。
using System;
using System.Threading;
using System.Threading.Tasks;class Program
{static void Main(){// 使用Task.Factory.StartNewTask task1 = Task.Factory.StartNew(PrintNumbers);// 使用Task.Run (简化版)Task task2 = Task.Run(() => PrintNumbersWithDelay(400));// 带返回值的任务Task<int> task3 = Task.Run(() => CalculateSum(10));Console.WriteLine($"计算结果: {task3.Result}");Console.WriteLine("主线程继续执行...");Task.WaitAll(task1, task2); // 等待所有任务完成Console.ReadLine();}static void PrintNumbers(){for (int i = 1; i <= 5; i++){Console.WriteLine($"任务1: {i}");Thread.Sleep(100);}}static void PrintNumbersWithDelay(int delay){for (int i = 1; i <= 5; i++){Console.WriteLine($"任务2: {i}");Thread.Sleep(delay);}}static int CalculateSum(int n){int sum = 0;for (int i = 1; i <= n; i++){sum += i;Thread.Sleep(50);}return sum;}
}
4. 使用async/await关键字
async
和await
关键字是.NET 4.5引入的语法糖,它基于TPL构建,能够让异步代码看起来更像同步代码。
using System;
using System.Threading;
using System.Threading.Tasks;class Program
{static async Task Main(){Console.WriteLine("主线程开始...");// 启动异步任务Task task1 = PrintNumbersAsync();Task<int> task2 = CalculateSumAsync(15);// 等待任务完成await task1;Console.WriteLine($"计算结果: {await task2}");Console.WriteLine("主线程结束.");Console.ReadLine();}static async Task PrintNumbersAsync(){await Task.Run(() =>{for (int i = 1; i <= 5; i++){Console.WriteLine($"异步任务: {i}");Thread.Sleep(200);}});}static async Task<int> CalculateSumAsync(int n){return await Task.Run(() =>{int sum = 0;for (int i = 1; i <= n; i++){sum += i;Thread.Sleep(100);}return sum;});}
}
5. 使用BackgroundWorker组件(Windows Forms/WPF环境)
在Windows Forms或WPF应用程序中,可以使用BackgroundWorker
组件来执行后台操作,并且能够与UI线程进行安全通信。
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;namespace BackgroundWorkerExample
{public partial class Form1 : Form{private BackgroundWorker backgroundWorker1;public Form1(){InitializeComponent();// 初始化BackgroundWorkerbackgroundWorker1 = new BackgroundWorker();backgroundWorker1.DoWork += BackgroundWorker1_DoWork;backgroundWorker1.ProgressChanged += BackgroundWorker1_ProgressChanged;backgroundWorker1.RunWorkerCompleted += BackgroundWorker1_RunWorkerCompleted;backgroundWorker1.WorkerReportsProgress = true;backgroundWorker1.WorkerSupportsCancellation = true;}private void buttonStart_Click(object sender, EventArgs e){if (!backgroundWorker1.IsBusy){backgroundWorker1.RunWorkerAsync(10); // 传递参数}}private void buttonCancel_Click(object sender, EventArgs e){if (backgroundWorker1.WorkerSupportsCancellation){backgroundWorker1.CancelAsync();}}private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e){BackgroundWorker worker = sender as BackgroundWorker;int max = (int)e.Argument;for (int i = 1; i <= max; i++){if (worker.CancellationPending){e.Cancel = true;break;}else{// 执行工作Thread.Sleep(500);worker.ReportProgress(i * 10);}}e.Result = max;}private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e){// 更新UI(安全操作)progressBar1.Value = e.ProgressPercentage;labelStatus.Text = $"完成 {e.ProgressPercentage}%";}private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){if (e.Cancelled){labelStatus.Text = "操作已取消";}else if (e.Error != null){labelStatus.Text = $"错误: {e.Error.Message}";}else{labelStatus.Text = $"操作完成,结果: {e.Result}";}}}
}
总结
- Thread类:适合用于需要对线程进行精细控制的场景。
- ThreadPool:在执行短时间任务且需要复用线程的情况下是不错的选择。
- Task Parallel Library (TPL):推荐在大多数情况下使用,尤其是需要处理任务组合和结果的场景。
- async/await:非常适合编写异步代码,能让代码的可读性更强。
- BackgroundWorker:专门用于Windows Forms和WPF应用程序中进行后台操作并更新UI。
你可以根据具体的使用场景,挑选最合适的线程创建方式。