IT评测·应用市场-qidao123.com

标题: C# 多线程 [打印本页]

作者: 忿忿的泥巴坨    时间: 2023-5-30 00:28
标题: C# 多线程
什么是线程 Thread


线程的一些属性

Join and Sleep


阻塞 Blocking

bool blocked = (someThread.ThreadState & ThreadState.WaitsleepJoin) != 0;
ThreadState

解除阻塞 Unblocking

上下文切换

l/O-bound vs Compute-bound(或 CPU-Bound )

阻塞Blocking vs 忙等待(自旋)Spinning

什么是线程安全?

本地Local  vs  共享的状态Shared State

Local本地独立

Shared共享

  1. internal class Program {
  2.     static bool _done;
  3.     static void Main(string[] args) {
  4.         new Thread(Do).Start();
  5.         Do();
  6.     }
  7.     static void Do() {
  8.         if(!_done) {
  9.             _done = true;
  10.             Console.WriteLine("Done!");
  11.         }
  12.     }
  13. }
复制代码
线程安全 Thread Safety


锁定与线程安全简介

  1. internal class Program {
  2.     static bool _done;
  3.     static readonly object _lock = new object();
  4.    
  5.     static void Main(string[] args) {
  6.         new Thread(Do).Start();
  7.         Do();
  8.     }
  9.     static void Do() {
  10.         lock (_lock) {
  11.             if (!_done) {
  12.                 Console.WriteLine("Done!");
  13.                 Thread.Sleep(100);
  14.                 _done = true;
  15.             }
  16.         }
  17.     }
  18. }
复制代码
向线程传递数据

  1. internal class Program {
  2.     static bool _done;
  3.     static readonly object _lock = new object();
  4.     static void Main(string[] args) {
  5.         new Thread(() => {
  6.             PrintThing("Hello,World!");
  7.         }).Start();
  8.         new Thread(() => {
  9.             Console.WriteLine("Hello World!");
  10.         }).Start();
  11.         //注意C#3.0 之前在Start里传递参数,此时thing 的类型必须为object
  12.         new Thread(PrintThing).Start("Hello World!");
  13.     }
  14.     static void PrintThing(object thing) {
  15.         Console.WriteLine("信息:" + thing);
  16.     }
  17. }
复制代码
异常处理

  1. internal class Program {
  2.     static bool _done;
  3.     static readonly object _lock = new object();
  4.     static void Main(string[] args) {
  5.         new Thread(DoThrow).Start();
  6.     }
  7.     static void DoThrow() {
  8.         try {
  9.             throw null;
  10.         } catch {
  11.             Console.WriteLine("发生异常");
  12.         }
  13.     }
  14. }
复制代码
前台线程 vs 后台线程

线程优先级

提高线程优先级

  1. using (Process p = Process.GetCurrentProcess())
  2. p.Priorityclass = ProcessPriorityclass.High;
复制代码
信号 Signaling

  1. static void Main(string[] args) {
  2.     var signal = new ManualResetEvent(false);
  3.     new Thread(() => {
  4.         Console.WriteLine("等待信号。。。");
  5.         signal.WaitOne();//收到Set()发出的信号之前,停在这里
  6.         signal.Dispose();
  7.         Console.WriteLine("收到信号。");
  8.     }).Start();
  9.     Thread.Sleep(3000);//这里等待3s,Main线程再发送信号Set()
  10.     signal.Set();
  11. }
复制代码
富客户端应用程序的线程

示例:

同步上下文 Synchronization Context

线程池 ThreadPool

使用线程池线程需要注意的几点

线程池中的整洁

CLR的策略

<ul>CLR通过对任务排队并对其启动进行节流限制来避免线程池中的超额订阅。
它首先运行尽可能多的并发任务(只要还有CPU核),然后通过爬山算法调整并发级别,并在特定方向上不断调整工作负载.
这确保它始终追随最佳性能曲线,即使面对计算机上竞争的进程活动时也是如此
如果下面两点能够满足,那么CLR的策略将发挥出最佳效果:<ul>
工作项大多是短时间运行的 ({        Console.WriteLine("开启一个线程");});TaskFactory factory=new TaskFactory();factory.StartNew(()=>{        Console.WriteLine("开启一个线程");});TaskFactory factory2=Task.Factory();factory2.StartNew(()=>{        Console.WriteLine("开启一个线程");});[/code]等待 Wait


Long-running tasks长时间运行的任务

Task的线程等待和延续

Wait:针对单个Task的实例,可以task1.wait进行线程等待
WaitAny:线程列表中任何一个线程执行完毕即可执行(阻塞主线程)
WaitAll:线程列表中所有线程执行完毕方可执行(阻塞主线程)
WhenAny:与ContinueWith配合,线程列表中任何一个执行完毕,则继续ContinueWith中的任务(开启新线程,不阻塞主线程)
WhenAll:与ContinueWith配合,线程列表中所有线程执行完毕,则继续ContinueWith中的任务(开启新线程,不阻塞主线程)
ContinueWith:与WhenAny或WhenAll配合使用
ContinueWhenAny:等价于Task的WhenAny+ContinueWith
ContinueWhenAll:等价于Task的WhenAll+ContinueWith
  1. Task task=new Task(()=>{
  2.         Console.WriteLine("开启一个线程");
  3. });
  4. task.Start();
  5. Task.Run(()=>{
  6.         Console.WriteLine("开启一个线程");
  7. });
  8. TaskFactory factory=new TaskFactory();
  9. factory.StartNew(()=>{
  10.         Console.WriteLine("开启一个线程");
  11. });
  12. TaskFactory factory2=Task.Factory();
  13. factory2.StartNew(()=>{
  14.         Console.WriteLine("开启一个线程");
  15. });
复制代码
Task取消

Task中有一个专门的类 CancellationTokenSource 来取消任务执行。
  1. List<Task> taskList = new List<Task>();
  2. TaskFactory factory = Task.Factory;
  3. taskList.Add(factory.StartNew(() => {
  4.     Thread.Sleep(4000);
  5.     MessageBox.Show($"{Task.CurrentId}");
  6. }));
  7. taskList.Add(factory.StartNew(() => {
  8.     Thread.Sleep(6000);
  9.     MessageBox.Show($"{Task.CurrentId}");
  10. }));
  11. taskList.Add(factory.StartNew(() => {
  12.     Thread.Sleep(8000);
  13.     MessageBox.Show($"{Task.CurrentId}");
  14. }));
  15. Task.WaitAny(taskList.ToArray()); // 1-main-2-3 会阻塞主线程
  16. Task.WaitAll(taskList.ToArray());   // 1-2-3-main 会阻塞主线程
  17. Task.WhenAny(taskList.ToArray()).ContinueWith(t => {
  18.     MessageBox.Show("1个已经执行完");
  19. }); // main-1-"1个已经执行完"-2-3 不会阻塞主线程
  20. Task.WhenAll(taskList.ToArray()).ContinueWith(t => {
  21.     MessageBox.Show("全部已经执行完");
  22. }); // main-1-2-3-"全部已经执行完" 不会阻塞主线程
  23. factory.ContinueWhenAny(taskList.ToArray(), t => {
  24.     MessageBox.Show("1个已经执行完");
  25. }); // main-1-"1个已经执行完"-2-3 不会阻塞主线程  等价于Task的WhenAny+ContinueWith
  26. factory.ContinueWhenAll(taskList.ToArray(), t => {
  27.     MessageBox.Show("全部已经执行完");
  28. }); // main-1-2-3-"全部已经执行完" 不会阻塞主线程   等价于Task的WhenAll+ContinueWith
  29. MessageBox.Show("main");
复制代码
Task返回值


Task异常


异常与“自治”的Task

未观察到的异常


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4