当前位置: 首页 > news >正文

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关键字

asyncawait关键字是.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。

你可以根据具体的使用场景,挑选最合适的线程创建方式。

相关文章:

  • 基于LLM合成高质量情感数据,提升情感分类能力!!
  • 程序人生-Hello’s P2P
  • C语言| 指针变量的定义
  • c++ 运算符重载
  • 【LINUX操作系统】生产者消费者模型(下):封装、信号量与环形队列
  • 【Spring】Spring的请求处理
  • SVGPlay:一次 CodeBuddy 主动构建的动画工具之旅
  • 融智学视域下的系统性认知增强框架——基于文理工三类AI助理赋能HI四阶跃迁路径
  • Linux调试生成核心存储文件
  • python线程相关讲解
  • 从0到1:Python项目部署与运维全攻略(10/10)
  • Flowbite 和 daisyUI 那个好用?
  • 数字化转型- 数字化转型路线和推进
  • 【四川省专升本计算机基础】第二章 计算机软硬件基础(2)
  • USRP 射频信号 采集 回放 系统
  • Python基础学习-Day27
  • 【Changer解码头详解及融入neck层数据的实验设计】
  • C#与KepOPC通讯
  • 手动实现 Transformer 模型
  • LeetCode --- 156双周赛
  • 视频丨为救心梗同学缺席职教高考的小伙姜昭鹏完成补考
  • 回家了!子弹库帛书二、三卷将于7月首次面向公众展出
  • 广西壮族自治区党委副书记、自治区政府主席蓝天立接受审查调查
  • 《日出》华丽的悲凉,何赛飞和赵文瑄演绎出来了
  • 埃尔多安:愿在土耳其促成俄乌领导人会晤
  • 苏轼“胡为适南海”?