我正在为传统的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以进行比较。
答案 0 :(得分:2)
在.NET 2.0中为自定义CLR主机引入了将托管线程映射到自定义线程方案的功能。具体来说,SQL Server。他们想使用光纤,这是SQL Server的原生功能。他们无法解决这个问题,该项目被搁置了。我现在还没有知道实际利用该功能的CLR主机。
它永远不会成为默认CLR主机中的问题,即WPF应用程序中的主机。托管线程始终映射到一个OS线程并始终如此。您可以依赖GetCurrentThreadId()返回的值。我严重怀疑将永远改变,这将是一个重大的突破性变化。对于某种类型的未来主机,这可能不太适用,类似于Silverlight,但您的代码永远不会接近它。