当前位置: 首页 > 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。

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

http://www.xdnf.cn/news/503893.html

相关文章:

  • 一字典两世界:优雅移除 `NSDictionary` 指定键的最佳实践
  • 编程基础:什么是变量
  • 《 C语言中const修饰指针变量的用法与解析》
  • 解决米勒补偿右边零点的方法
  • 【蓝桥杯省赛真题51】python石头运输 第十五届蓝桥杯青少组Python编程省赛真题解析
  • mcp学习笔记
  • day 28
  • ECS/GEM是半导体制造业的标准通信协议中host和equipment的区别是什么,在交互过程中,如何来定位角色谁为host,谁为equipment
  • Spring Boot 中 MyBatis 与 Spring Data JPA 的对比介绍
  • 【Python 算法零基础 3.递推】
  • 【C语言】链接与编译(编译环境 )
  • 配置ssh服务-ubuntu到Windows拷贝文件方法
  • Java Records:简洁的数据建模新方式
  • ubuntu 24.04安装ros1 noetic
  • 历史数据分析——中证白酒
  • 数据库3——视图及安全性
  • 计算机网络体系结构深度解析:从理论到实践的全面梳理
  • 电动调节 V 型球阀:工业流体控制的全能解决方案-耀圣
  • 高考AI试题查询系统
  • 网络切片:给用户体验做“私人定制”的秘密武器
  • 80. Java 枚举类 - 使用枚举实现单例模式
  • 自制操作系统(三、文件系统实现)
  • 8天Python从入门到精通【itheima】-14~16
  • 【PhysUnits】4.2 Integer Trait
  • c/c++的opencv的轮廓匹配初识
  • 提升Qt应用性能--全面解析关键技术与策略
  • C++性能测试工具——Vtune的使用
  • BC 范式与 4NF
  • 全局异常处理:如何优雅地统一管理业务异常
  • Android屏幕采集编码打包推送RTMP技术详解:从开发到优化与应用