.NET 多线程 C# 多线程 持续更新、完善、进化

打印 上一主题 下一主题

主题 991|帖子 991|积分 2973

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在 .NET情况下,多线程编程主要有 Thread ThreadPool Task Parallel BackgroundWorker 等几种,另有一个与多线程干系的:异步编程 async/await ,值得夸大的是,异步编程不等于多线程 。当然,这几种多线程编程的方式并不是独立开的,在底层的封装有肯定的接洽。
1. Thread 

1.1 底子应用

引用Thread的命名空间
  1. using System;
  2. using System.Threading;
复制代码
直接创建线程举行启动
  1. static void Main()
  2. {
  3.     // 创建一个新线程
  4.     Thread thread = new Thread(DoWork);
  5.     thread.Start(); // 启动线程
  6.     // 主线程继续执行
  7.     for (int i = 0; i < 10; i++)
  8.     {
  9.         Console.WriteLine("这是主线程打印: " + i);
  10.         Thread.Sleep(500);
  11.     }
  12.     Console.ReadKey();
  13. }
  14. static void DoWork()
  15. {
  16.     for (int i = 0; i < 10; i++)
  17.     {
  18.         Console.WriteLine("这是自主创建的线程打印: " + i);
  19.         Thread.Sleep(500);
  20.     }
  21. }
复制代码
调试结果:
  1. 这是自主创建的线程打印: 0
  2. 这是主线程打印: 0
  3. 这是自主创建的线程打印: 1
  4. 这是主线程打印: 1
  5. 这是主线程打印: 2
  6. 这是自主创建的线程打印: 2
  7. 这是主线程打印: 3
  8. 这是自主创建的线程打印: 3
  9. 这是主线程打印: 4
  10. 这是自主创建的线程打印: 4
  11. 这是主线程打印: 5
  12. 这是自主创建的线程打印: 5
  13. 这是主线程打印: 6
  14. 这是自主创建的线程打印: 6
  15. 这是主线程打印: 7
  16. 这是自主创建的线程打印: 7
  17. 这是主线程打印: 8
  18. 这是自主创建的线程打印: 8
  19. 这是主线程打印: 9
  20. 这是自主创建的线程打印: 9
复制代码
可以发现,主线程和自己创建的线程各干各的,互不耽搁。
1.2 线程入参

如果我在启动线程时想给他一个参数呢?这样搞:
1. 在委托方法设置参数

  1. static void Main()
  2. {
  3.     // 创建一个新线程
  4.     Thread thread = new Thread(DoWork);
  5.     thread.Start("子线程启动啦"); // 启动线程
  6.     // 主线程继续执行
  7.     for (int i = 0; i < 10; i++)
  8.     {
  9.         Console.WriteLine("这是主线程打印: " + i);
  10.         Thread.Sleep(500);
  11.     }
  12.     Console.ReadKey();
  13. }
  14. static void DoWork(object obj)
  15. {
  16.     // 将传入的 object 类型参数转换为实际类型
  17.     string message = (string)obj;
  18.     Console.WriteLine($"Received message in Main thread: {message}");
  19.     for (int i = 0; i < 10; i++)
  20.     {
  21.         Console.WriteLine("这是自主创建的线程打印: " + i);
  22.         Thread.Sleep(500);
  23.     }
  24. }
复制代码
调试结果:
  1. 这是主线程打印: 0
  2. Received message in Main thread: 子线程启动啦
  3. 这是自主创建的线程打印: 0
  4. 这是自主创建的线程打印: 1
  5. 这是主线程打印: 1
  6. 这是主线程打印: 2
  7. 这是自主创建的线程打印: 2
  8. 这是主线程打印: 3
  9. 这是自主创建的线程打印: 3
  10. 这是主线程打印: 4
  11. 这是自主创建的线程打印: 4
  12. 这是主线程打印: 5
  13. 这是自主创建的线程打印: 5
  14. 这是主线程打印: 6
  15. 这是自主创建的线程打印: 6
  16. 这是主线程打印: 7
  17. 这是自主创建的线程打印: 7
  18. 这是自主创建的线程打印: 8
  19. 这是主线程打印: 8
  20. 这是主线程打印: 9
  21. 这是自主创建的线程打印: 9
复制代码
2. 使用Lambda表达式

  1. static void Main()
  2. {
  3.     // 创建一个新线程
  4.     // 使用 Lambda 表达式创建线程并传递参数
  5.     Thread thread = new Thread(() =>
  6.     {
  7.         DoWork("子线程又又又启动啦");
  8.     });
  9.     // 启动线程
  10.     thread.Start();
  11.     // 主线程继续执行
  12.     for (int i = 0; i < 10; i++)
  13.     {
  14.         Console.WriteLine("这是主线程打印: " + i);
  15.         Thread.Sleep(500);
  16.     }
  17.     Console.ReadKey();
  18. }
  19. static void DoWork(object obj)
  20. {
  21.     // 将传入的 object 类型参数转换为实际类型
  22.     string message = (string)obj;
  23.     Console.WriteLine($"Received message in Main thread: {message}");
  24.     for (int i = 0; i < 10; i++)
  25.     {
  26.         Console.WriteLine("这是自主创建的线程打印: " + i);
  27.         Thread.Sleep(500);
  28.     }
  29. }
复制代码
调试运行结果:
  1. 这是主线程打印: 0
  2. Received message in Main thread: 子线程又又又启动啦
  3. 这是自主创建的线程打印: 0
  4. 这是主线程打印: 1
  5. 这是自主创建的线程打印: 1
  6. 这是主线程打印: 2
  7. 这是自主创建的线程打印: 2
  8. 这是主线程打印: 3
  9. 这是自主创建的线程打印: 3
  10. 这是主线程打印: 4
  11. 这是自主创建的线程打印: 4
  12. 这是主线程打印: 5
  13. 这是自主创建的线程打印: 5
  14. 这是主线程打印: 6
  15. 这是自主创建的线程打印: 6
  16. 这是主线程打印: 7
  17. 这是自主创建的线程打印: 7
  18. 这是主线程打印: 8
  19. 这是自主创建的线程打印: 8
  20. 这是主线程打印: 9
  21. 这是自主创建的线程打印: 9
复制代码
2. ThreadPool 

System.Threading.ThreadPool 是一个线程池,用于管理和复用线程,得当处理大量短生命周期的任务。着实这个是对Thread的封装,从某种程度上讲节省了步伐运行的开销。
  1. static void Main()
  2. {
  3.     // 将任务加入线程池
  4.     ThreadPool.QueueUserWorkItem(DoWork);
  5.     // 主线程继续执行
  6.     for (int i = 0; i < 10; i++)
  7.     {
  8.         Console.WriteLine("这是主线程打印: " + i);
  9.         Thread.Sleep(500);
  10.     }
  11.     Console.ReadKey();
  12. }
  13. static void DoWork(object obj)
  14. {
  15.     // 将传入的 object 类型参数转换为实际类型
  16.     string message = (string)obj;
  17.     Console.WriteLine($"Received message in Main thread: {message}");
  18.     for (int i = 0; i < 10; i++)
  19.     {
  20.         Console.WriteLine("这是自主创建的线程打印: " + i);
  21.         Thread.Sleep(500);
  22.     }
  23. }
复制代码
运行调试结果
  1. 这是主线程打印: 0
  2. Received message in Main thread:
  3. 这是自主创建的线程打印: 0
  4. 这是自主创建的线程打印: 1
  5. 这是主线程打印: 1
  6. 这是主线程打印: 2
  7. 这是自主创建的线程打印: 2
  8. 这是主线程打印: 3
  9. 这是自主创建的线程打印: 3
  10. 这是主线程打印: 4
  11. 这是自主创建的线程打印: 4
  12. 这是主线程打印: 5
  13. 这是自主创建的线程打印: 5
复制代码
3. Task 

System.Threading.Tasks.Task 是基于任务的异步编程模型(TAP),是对ThreadPool的进一步封装,提供了更高级的功能。感觉套娃是微软的强项哈哈。
  1. static void Main()
  2. {
  3.     // 创建一个任务并启动
  4.     Task task = Task.Run(() => DoWork());
  5.     // 主线程继续执行
  6.     for (int i = 0; i < 4; i++)
  7.     {
  8.         Console.WriteLine("这是主线程打印: " + i);
  9.         Task.Delay(500).Wait();
  10.     }
  11.     task.Wait(); // 等待任务完成
  12.     Console.ReadKey();
  13. }
  14. static void DoWork()
  15. {
  16.    
  17.     for (int i = 0; i < 7; i++)
  18.     {
  19.         Console.WriteLine("这是自主创建的线程打印: " + i);
  20.         Thread.Sleep(500);
  21.     }
  22. }
复制代码
调试执行:
  1. 这是主线程打印: 0
  2. 这是自主创建的线程打印: 0
  3. 这是自主创建的线程打印: 1
  4. 这是主线程打印: 1
  5. 这是自主创建的线程打印: 2
  6. 这是主线程打印: 2
  7. 这是主线程打印: 3
  8. 这是自主创建的线程打印: 3
  9. 这是自主创建的线程打印: 4
  10. 这是自主创建的线程打印: 5
  11. 这是自主创建的线程打印: 6
复制代码
从综合性能和实战经验来看,Task应该是应用最多的,主要表现在以下几个特点


  • 支持任务并行和异步操作。
  • 可以获取任务的执行结果(通过Task<TResult>)。
  • 支持任务取消、延续和非常处理。
4. Parallel 

System.Threading.Tasks.Parallel 提供了简朴的并行循环和并行任务执行。
  1. // 并行执行循环
  2.         Parallel.For(0, 5, i =>
  3.         {
  4.             Console.WriteLine("Parallel thread: " + i);
  5.             Task.Delay(500).Wait();
  6.         });
复制代码
调试运行:
  1. Parallel thread: 3
  2. Parallel thread: 0
  3. Parallel thread: 4
  4. Parallel thread: 1
  5. Parallel thread: 2
复制代码


  • 简化并行循环的编写。
  • 主动管理线程池中的线程。
这种模式适用于任务并行分发的场景,简朴,高效。
5. BackgroundWorker

System.ComponentModel.BackgroundWorker 是一个用于在后台执行任务的组件,得当在UI应用步伐中使用。
代码示例:
  1. static void Main()
  2. {
  3.     BackgroundWorker worker = new BackgroundWorker();
  4.     worker.DoWork += DoWork;
  5.     worker.RunWorkerCompleted += WorkCompleted;
  6.     worker.RunWorkerAsync(); // 启动后台任务
  7.     Console.WriteLine("Main thread continues...");
  8.     Console.ReadKey();
  9. }
  10. static void DoWork(object sender, DoWorkEventArgs e)
  11. {
  12.     for (int i = 0; i < 5; i++)
  13.     {
  14.         Console.WriteLine("工作线程: " + i);
  15.         System.Threading.Thread.Sleep(500);
  16.     }
  17. }
  18. static void WorkCompleted(object sender, RunWorkerCompletedEventArgs e)
  19. {
  20.     Console.WriteLine("任务完成.");
  21. }
复制代码
运行结果:
  1. Main thread continues...
  2. 工作线程: 0
  3. 工作线程: 1
  4. 工作线程: 2
  5. 工作线程: 3
  6. 工作线程: 4
  7. 任务完成.
复制代码

6. async/await

async/await不是多线程。只是和多线程干系,详细来说是和Task直接干系。
代码示例1:
  1. static async Task Main()
  2. {
  3.     Console.WriteLine("主线程启动.");
  4.     // 异步调用
  5.     await DoWorkAsync();
  6.     Console.WriteLine("主线程完成.");
  7.     Console.ReadKey();
  8. }
  9. static async Task DoWorkAsync()
  10. {
  11.     for (int i = 0; i < 5; i++)
  12.     {
  13.         Console.WriteLine("异步方法执行: " + i);
  14.         await Task.Delay(500);
  15.     }
  16. }
复制代码
运行结果:
  1. 主线程启动.
  2. 异步方法执行: 0
  3. 异步方法执行: 1
  4. 异步方法执行: 2
  5. 异步方法执行: 3
  6. 异步方法执行: 4
  7. 主线程完成.
复制代码
大概这样写:
  1. static async Task DoWorkAsync()
  2. {
  3.     for (int i = 0; i < 5; i++)
  4.     {
  5.         await Task.Run(() =>
  6.         {
  7.             Console.WriteLine("异步方法执行: " + i);
  8.             Task.Delay(500);
  9.         });
  10.     }
  11. }
复制代码
关于异步编程,在杨中科的书里学了一点:第2章 .NETCore异步编程 C#异步编程 关键字async/await用法
DeepSeek总结:
种类适用场景优点缺点Thread需要精细控制线程的场景直接控制线程生命周期手动管理线程,开销较大ThreadPool大量短生命周期任务线程复用,减少开销不得当长时间任务Task异步编程和任务并行功能强盛,支持任务结果和非常处理需要理解异步编程模型Parallel简朴的并行循环简化并行编程不得当复杂任务async/await异步编程,避免阻塞主线程代码简便,易于理解需要理解异步编程模型BackgroundWorkerUI应用步伐中的后台任务支持进度陈诉和取消操作功能相对简朴 7. 线程间的通讯



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美丽的神话

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表