C# 多线程学习笔记 - 1
本文主要针对 GKarch 相关文章留作笔记,仅在原文基础上记录了自己的理解与摘抄部分片段。
遵循原作者的 CC 3.0 协议。
如果想要了解更加详细的文章信息内容,请访问下列地址进行学习。
基础知识
- 静态字段是在所有线程当中共享状态的。
- 一个线程被阻塞时,不会消耗 CPU 资源。
- Join 可以等待另一个线程结束,Sleep 可以将线程阻塞指定的时间,两者使用时线程都是阻塞状态。
- Join 可以设置超时时间,当线程执行超过指定时间返回 False。
Thread.Sleep(0)
会释放当前时间片,将 CPU 资源让出给其他线程。Thread.Sleep(0)
作用与Thread.Yield()
作用一样,后者只会让出给当前核心的其他线程。Thread.Yield()
执行时会影响到程序的话,基本可以确定代码存在 Bug。- 在使用 Lambda 表达式启动线程并传入变量的时候,不要在启动线程之后更改被捕获变量的值。
- 线程分为前台线程与后台线程,当所有前台线程中止时,程序自动退出。
- 可以显式地提高线程优先级,但可能会导致线程饥饿。
线程池
-
由于线程创建成本高昂(私有局部变量栈,每个线程默认占用 1 MB内存),所以一般都会使用线程池来进行线程的创建与回收。
-
线程池线程可以临时更改其优先级,在回收后会恢复默认状态。
-
开发人员可以通过
Thread.CurrentThread.IsThreadPoolThread
属性查询线程是否运行在线程池中。 -
通过查询 Task.Result 会导致当前线程阻塞,直到任务执行完成,如果发生错误,则会将异常包装到
AggregateException
异常内进行抛出。 -
通过异步委托可以快速创建一个工作线程。
- 创建目标方法委托。
- 在委托上调用
BeginInvoke()
方法,保存其IActionResult
返回值。 - 需要返回结果时,调用
EndInvoke()
方法,传递保存的IActionResult
对象。
class Program { static void Main(string[] args) { Func<string, int> work = Work; var result = work.("测试",null,null); Console.WriteLine("获得结果"); work.EndInvoke(result); } public static int Work(string inputStr) { Console.Write(Thread.CurrentThread); return inputStr.Length; } }
注意:
上述代码在 .NET Core 平台上是无法运行的。
-
异步委托在调用
BeginInvoke()
的时候可以传入回调方法。 -
线程池可以通过
ThreadPool.SetMaxThreads
与ThreadPool.SetMinThreads
进行优化。