用于Windows API调用的AppDomain.GetCurrentThreadID vs Thread.ManagedThreadID?

Fro*_*840 15 .net vb.net winapi

我正在尝试创建一个钩子来监视鼠标光标的当前位置.没什么重要的,我只需要在界面设计中计算一些像素,并想学习如何创建一个钩子,所以我决定采用一种艰难的方式而不是一种理智的方式.

我找到了声明以下函数的示例代码:

 <DllImport("User32.dll", CharSet:=CharSet.Auto, _
 CallingConvention:=CallingConvention.StdCall)> _
 Public Overloads Shared Function SetWindowsHookEx _
      (ByVal idHook As Integer, ByVal HookProc As CallBack, _
       ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
End Function
Run Code Online (Sandbox Code Playgroud)

调用该函数时,使用以下代码:

        hHook = SetWindowsHookEx(WH_MOUSE, _
                                 hookproc, _
                                 IntPtr.Zero, _
                                 AppDomain.GetCurrentThreadId())
Run Code Online (Sandbox Code Playgroud)

但是Appdomain.GetCurrentThreadID生成警告:"'公共共享函数GetCurrentThreadId()As Integer'已过时:'AppDomain.GetCurrentThreadId已被弃用,因为当托管线程在光纤(又称轻量级线程)上运行时,它不提供稳定的Id.要获取托管线程的稳定标识符,请使用Thread上的ManagedThreadId属性."

我尝试过使用ManagedThreadID,但这不起作用.返回的线程ID似乎是线程的逻辑线程ID,因为它在.net运行时运行,而不是Win32线程标识符.

调用函数ith AppDomain.GetCurrentThreadID有效,但我真的想为我的线程提供一个"稳定的标识符".

有人可以向我解释是否可以在此上下文中使用ManagedThreadID(我假设不是),如果没有,我需要避免的事情是为了阻止AppDomain.CurrentThreadID变得"不稳定"?

干杯

Jar*_*Par 14

在此上下文中无法使用ManagedThreadId.这是一个完全管理的概念,在本地世界中没有真正的代表.因此,对你传递给它的API没有任何意义.

ManagedThreadId存在的原因是因为本机和托管线程之间不一定有1-1映射.只要本机线程与其替换的线程兼容,CLR就可以自由地使用多个本机线程来运行单个托管线程.例如,它不能在不同的COM公寓中.

在某些方面你有点卡在这里.AFAIK,没有办法100%保证您将为给定的托管线程拥有相同的本机线程.如果您运行WinForms或WPF应用程序并且在UI线程上调用本机代码,则可以实现非常高级别的保证.原因是这两个UI框架都存在于STA公寓中,这使得CLR很难(如果可能的话)从您下面切换出来.

简短版本:如果您在WinForms或WPF应用程序中并在UI线程上运行它,则可以为此标识符假设合理的稳定性级别.


小智 5

你可以使用:

using System.Diagnostics;
Process.GetCurrentProcess().Threads[0].Id
Run Code Online (Sandbox Code Playgroud)

代替

AppDomain.GetCurrentThreadId()

问题只是在运行的线程数多于主线程 0 的情况下找到正确的线程数。