我想要一个与应用程序的主 UI 线程相关联的表单拥有几个其他表单,每个表单都有自己的线程(每个表单都与一个硬件相关联,我希望在这些表单上处理更新,即使主窗体忙了一秒钟左右)。所有权的主要期望目的是维护窗口堆叠行为(拥有的窗体按 Z 顺序保持在所有者之上,但不会强制在其他应用程序的窗口之上)。
关于 SO 的许多问题询问如何执行此操作,并且答案表明在更改所有权时可能会CheckForIllegalCrossThreadCalls
短暂设置为 false,但被警告对冲,表明人们认为该方法不知道它是否真的安全。
我可以看到这些方法至少有两个可能的问题:
更改
Owner
表单将有效地调用AddOwnedForm
和/或其RemoveOwnedForm
所有者。我不希望设置CheckForIllegalCrossThreadCalls
为 false 会使该方法成为线程安全的。如果同时显示或隐藏绑定到不同线程的多个表单,则可能会出现问题。我希望使用类似的东西NewOwner.Invoke(() => NewOwner.AddOwnedForm(this))
可以缓解这个问题。据我所知,
CheckForIllegalCrossThreadCalls
是一个全局属性。因此,我担心如果两个线程同时将其设置为 false,一个线程可能会将其设置为 true,而另一个线程仍需要将其设置为 false。将CheckForIllegalCrossThreadCalls
清除和重新设置作为传递给跨线程的方法的一部分Invoke
似乎可以解决问题,如果主 UI 线程是唯一写入该属性的线程,但我不知道是否存在可能是在任何 .NET UI 代码中对该属性“隐藏”的任何写入。
目前,有问题的应用程序仅供内部使用。另一方面,如果有一种方法可以被认为对生产代码足够健壮,那就太好了。写完其他回复后,这方面有什么新发现吗?建议的方法(在主线程中处理所有权获取/释放)是否足以使事情变得健壮?
PS--如果有某种方法可以让子 MDI 窗口使用其他线程,那就更好了;从概念上讲,没有理由不可能做到这一点(a 和父 MDI 窗口应该对彼此产生的唯一影响是当子窗口被添加或从父窗口的子窗口列表中删除时(情况类似于拥有的窗口),或者当子窗口被移动并暴露一些父窗口时(这很像其他应用程序的窗口被移动并暴露父窗口的情况 - 显然 WinForms 经常处理的情况)。