父线程 在创建了子线程后,是不是继续执行自己的代码 ?(收集整理)
#多线程#thread
lock 与 Monitor 的等价关系
lock(obj) { … }实际上是Monitor.Enter(obj)与try…finally包装的语法糖。- 当你需要 超时等待、尝试获取锁(
TryEnter)或 在同一对象上进行多次嵌套锁定(递归锁)时,直接使用Monitor更加灵活。 - 对于 简单的互斥 场景,
lock已经足够安全且易读。
常见误区
- 不要在
lock中执行耗时操作(如网络 I/O、磁盘写入),否则会导致其他线程长时间阻塞。 - 避免锁的嵌套(两个锁相互嵌套)导致死锁。若必须嵌套,确保获取锁的顺序保持一致。
- 不要锁定
this或公开的对象,因为外部代码也可能尝试锁定同一对象,引发不可预期的竞争。
消息队列、UI 线程与跨线程调用
在 Windows 桌面应用(尤其是 WinForms)中,每个线程都有自己的消息队列,这与前面讨论的线程概念相互补充。原文对消息队列的生成与使用做了如下描述:
- 一个进程开始时至少会有一个主线程(即主执行实例),这是在系统加载你的程序的时候所创建的主执行流程。而消息队列则是与线程(
Thread)相关的,在类似 Win2K 上一个线程有一个且只有一个消息队列(queue)与之相对应。消息队列是在什么时候生成的呢? 在类似 Win2K 系统上,从一开始创建线程就已经有了。一个线程可以创建多个窗体。系统发送给这些窗口的消息都统一发送到同一个消息队列中,幸亏消息结构中有msg.hwnd指出该条消息与哪一个窗口相关,DispatchMessage()函数就是依照这个保证消息分派处理自动化而且不会出错!
UI 线程的唯一性
- 每个窗体(Form)都属于创建它的线程。这意味着 UI 控件只能在创建它们的线程上直接访问。
- 如果在 非 UI 线程 中直接访问控件(例如读取
TextBox.Text),会抛出 InvalidOperationException(跨线程操作无效)。
- 每个窗体都属于创建它的线程,在一线程中直接访或间接问其它线程中的窗体的方法将导致运行时错误(VS2005)。解决方法:使用窗体从
Control继承而来的Control.Invoke(Delegate)方法。该方法将在创建窗体的线程上执行委托指向的方法。注意:在 VS2003 下,可以在一个线程中直接或间接调用另一个线程中的窗体的方法,而不会导致运行时错误。