2009-04-21 46 views
15

我想創建一個鉤子來監視鼠標光標的當前位置。沒有什麼重要的,我只需要在界面設計中計算一些像素,並且想要學習如何創建一個鉤子,所以我決定採取一種艱難的方式,而不是一種理智的方式。針對Windows API調用的AppDomain.GetCurrentThreadID與Thread.ManagedThreadID?

其聲明如下功能我發現示例代碼:

<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 

當函數被調用時,下面的代碼被用於:

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

但Appdomain.GetCurrentThreadID生成警告: ''Public Shared Function GetCurrentThreadId()As Integer'已過時:'AppDomain.GetCurrentThreadId已被棄用,因爲當託管線程在光纖上運行時(也就是輕量級線程),它不會提供穩定的Id。日閱讀,使用Thread上的ManagedThreadId屬性。「

我試過使用ManagedThreadID,但那不起作用。返回的線程ID似乎是線程的邏輯線程ID,因爲它在.net運行時運行,而不是Win32線程標識符。

調用函數ith AppDomain.GetCurrentThreadID的作品,但我真的想爲我的線程有一個「穩定的標識符」。

有人可以向我解釋在這種情況下是否可以使用ManagedThreadID(我不假),如果沒有,我需要避免的事情,以阻止AppDomain.CurrentThreadID變得「不穩定」?

Cheers

+0

對於是否能夠找到解決此問題的解決方法感到好奇? – amadib 2010-10-28 19:34:00

+0

不是真的,沒有。我基本上只是用JaredPar的話來說,threadID會相當穩定,在測試過程中使用它,然後改變界面以對OnMouseMove事件做出反應,而不是最終部署。我原本沒有這樣做,因爲它意味着通過整個控制鏈傳遞事件,通常只是屁股疼痛。然而,它比上述方法更可靠,在整個測試過程中只失敗一次或兩次,但確實失敗了。 – Frosty840 2010-10-29 07:40:21

回答

13

在這種情況下不可能使用ManagedThreadId。這是一個完全管理的概念,在本土世界沒有真正的代表性。因此,對於您傳遞給它的API而言,這沒有任何意義。

ManagedThreadId存在的原因是因爲本地線程和託管線程之間不一定有1-1映射。只要本地線程與其替換的線程兼容,CLR就可以自由使用多個本地線程來運行單個託管線程。例如,它不能在不同的COM公寓中。

在某些方面,你有點卡在這裏。 AFAIK,沒有辦法100%保證你將有一個給定的託管線程相同的本地線程。您可以達到非常高的保證水平,例如,如果您正在運行WinForms或WPF應用程序,並且在UI線程上發生對本機代碼的調用。原因在於這兩個UI框架都住在STA公寓中,這使得CLR很難(如果可能的話)從你下面切換出來。簡短版本:如果您在WinForms或WPF應用程序中並在UI線程上運行此應用程序,則可以假設此標識符具有合理的穩定性級別。

3

對於將來的讀者: 還有System.Threading.Thread.BeginThreadAffinity()/ EndThreadAffinity()函數,它們聲稱阻止VM在不同物理線程之間切換。我不相信這些保證了穩定性,但我認爲他們更有可能保持穩定。

3

你可以使用:

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

,而不是

AppDomain.GetCurrentThreadId()

的問題才發現線程數正確,如果你有比主線程0運行多個線程。

3
var thread = Process.GetCurrentProcess().Threads.OfType<ProcessThread>(). 
    SingleOrDefault(x => x.ThreadState == ThreadState.Running); 

if (thread != null) 
{ 
    // do stuff here 
} 
0

使用:

[的DllImport( 「KERNEL32.DLL」)] 靜態外部UINT GetCurrentThreadId();