托管主UI线程是否保留在同一(非托管)操作系统线程中?

时间:2010-05-07 07:46:27

标签: c# .net wpf multithreading pinvoke

我正在为传统的Win32应用程序创建托管的WPF UI前端。 WPF前端是可执行文件;作为其启动例程的一部分,我在第二个线程中将遗留应用程序作为DLL启动。遗留应用程序的任何UI操作(包括CreateWindowsEx等)都会在主UI线程上调用。

作为应用程序关闭过程的一部分,我想要正确清理。除此之外,我想在所有非托管窗口上调用DestroyWindow,以便他们可以正确地清理自己。因此,在关机期间,我使用EnumWindows来尝试查找所有非托管窗口。然后我将DestroyWindow称为我生成的列表。它们运行在主UI线程上。

在此背景知识之后,就我的实际问题而言:
在EnumWindows的枚举过程中,我必须检查其中一个返回的顶级窗口是否是我的非托管窗口之一。我这样做是通过调用GetWindowThreadProcessId来获取窗口创建者的进程ID和线程ID。我可以将流程ID与Process.GetCurrentProcess().Id进行比较,以检查我的应用是否创建了它。

为了提高安全性,我还想看看我的主UI线程是否创建了窗口。但是,返回的线程id是OS的ThreadId(与托管线程id不同)。如this question中所述,CLR保留将托管线程重新调度到不同OS线程的权利。我是否可以依赖CLR“足够智能”从不为主UI线程执行此操作(由于UI的线程亲和性)?然后我可以调用GetCurrentThreadId来获取主UI线程的非托管线程ID以进行比较。

1 个答案:

答案 0 :(得分:2)

在.NET 2.0中为自定义CLR主机引入了将托管线程映射到自定义线程方案的功能。具体来说,SQL Server。他们想使用光纤,这是SQL Server的原生功能。他们无法解决这个问题,该项目被搁置了。我现在还没有知道实际利用该功能的CLR主机。

它永远不会成为默认CLR主机中的问题,即WPF应用程序中的主机。托管线程始终映射到一个OS线程并始终如此。您可以依赖GetCurrentThreadId()返回的值。我严重怀疑将永远改变,这将是一个重大的突破性变化。对于某种类型的未来主机,这可能不太适用,类似于Silverlight,但您的代码永远不会接近它。