Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AppDomain.GetCurrentThreadID vs Thread.ManagedThreadID for Windows API calls?

I'm trying to create a hook to monitor the current position of the mouse cursor. Nothing important, I just need to count some pixels during interface design and wanted to learn how to create a hook, so I decided to go for a hard way instead of a sane way.

I've found example code which declares the following function:

 <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

When the function is called, the following code is used:

        hHook = SetWindowsHookEx(WH_MOUSE, _
                                 hookproc, _
                                 IntPtr.Zero, _
                                 AppDomain.GetCurrentThreadId())

But Appdomain.GetCurrentThreadID generates the warning: "'Public Shared Function GetCurrentThreadId() As Integer' is obsolete: 'AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the ManagedThreadId property on Thread."

I've tried using ManagedThreadID, but that doesn't work. The thread ID returned seems to be the logical thread ID of the thread, as it runs in the .net runtime, rather than the Win32 thread identifier.

Calling the function ith AppDomain.GetCurrentThreadID works, but I really would like to have a "stable identifier" for my thread.

Can someone explain to me whether it is possible to use ManagedThreadID in this context (I assume not) and, if not, the things I need to avoid in order to stop the AppDomain.CurrentThreadID from becoming "unstable"?

Cheers

like image 235
Frosty840 Avatar asked Apr 21 '09 12:04

Frosty840


2 Answers

It is not possible to use ManagedThreadId in this context. This is a completely managed concept and has no real representation in the native world. Hence it doesn't make any sense to the API's you're passing it to.

The reason ManagedThreadId exists is because there is not necessarily a 1-1 mapping between a native and managed thread. The CLR is free to use multiple native threads to run a single managed thread as long as the native thread is compatible with the one it's replacing. It cannot for instance, be in a different COM apartment.

In some ways you're a bit stuck here. AFAIK, there is no way to 100% guarantee that you will have the same native thread for a given managed thread. You can achieve a very high level of guarantee though if you are for instance running a WinForms or WPF application and the call to native code occurs on the UI thread. The reason being that both of these UI frameworks live in STA apartments which makes it very hard (if even possible) for the CLR to switch out from under you.

Short Version: If you're in a WinForms or WPF application and running this on the UI thread, you can assume a reasonable level of stability for this identifier.

like image 98
JaredPar Avatar answered Oct 31 '22 11:10

JaredPar


You could use:

using System.Diagnostics;
Process.GetCurrentProcess().Threads[0].Id

instead of

AppDomain.GetCurrentThreadId()

The problem is only to find the correct number of the thread if you have more threads than the main thread 0 running.

like image 31
andie Avatar answered Oct 31 '22 09:10

andie