2009-04-21 10 views
15

Estoy intentando crear un gancho para controlar la posición actual del cursor del mouse. Nada importante, solo necesito contar algunos píxeles durante el diseño de la interfaz y quería aprender a crear un gancho, así que decidí ir por un camino difícil en lugar de hacerlo de una manera sensata.AppDomain.GetCurrentThreadID vs Thread.ManagedThreadID para llamadas a la API de Windows?

que he encontrado código de ejemplo que declara la siguiente función:

<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 

Cuando la función es llamada, se utiliza el siguiente código:

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

Pero Appdomain.GetCurrentThreadID genera la advertencia: "'Public Shared Function GetCurrentThreadId() As Integer' está obsoleto: 'AppDomain.GetCurrentThreadId ha quedado obsoleto porque no proporciona un Id estable cuando los hilos administrados se ejecutan en fibras (también conocidos como subprocesos ligeros). Para obtener un identificador estable para un manejado th leer, use la propiedad ManagedThreadId en el hilo. "

He intentado usar ManagedThreadID, pero eso no funciona. El Id. Del subproceso devuelto parece ser el Id. De subproceso lógico del subproceso, ya que se ejecuta en el tiempo de ejecución .net, en lugar del identificador de subproceso Win32.

Llamar a la función AppDomain.GetCurrentThreadID funciona, pero realmente me gustaría tener un "identificador estable" para mi hilo.

¿Puede alguien explicarme si es posible usar ManagedThreadID en este contexto (supongo que no) y, si no, las cosas que debo evitar para evitar que AppDomain.CurrentThreadID se vuelva "inestable"?

Saludos

+0

¿Te preocupa si pudiste encontrar una solución para este problema? – amadib

+0

No realmente, no. Básicamente, tomé la palabra de JaredPar para que el threadID fuera razonablemente estable, lo usé durante las pruebas y luego cambié la interfaz para reaccionar a los eventos de OnMouseMove en lugar de la implementación final. No lo hice originalmente porque significa pasar eventos a través de toda una cadena de controles y generalmente es solo un dolor en el culo. Sin embargo, es más confiable que el método anterior, que solo falló una o dos veces durante la totalidad de la prueba, pero falló. – Frosty840

Respuesta

13

No es posible utilizar ManagedThreadID en este contexto. Este es un concepto completamente administrado y no tiene una representación real en el mundo nativo. Por lo tanto, no tiene ningún sentido para la API a la que lo está pasando.

La razón por la que ManagedThreadId existe es porque no hay necesariamente una asignación 1-1 entre una cadena de caracteres nativa y administrada. CLR es libre de usar múltiples hilos nativos para ejecutar un único hilo administrado siempre que el hilo nativo sea compatible con el que está reemplazando. No puede, por ejemplo, estar en un departamento COM diferente.

De alguna manera estás un poco trabado aquí. AFAIK, no hay forma de garantizar al 100% que tendrá el mismo hilo nativo para un hilo gestionado determinado. Puede obtener un nivel muy alto de garantía si, por ejemplo, ejecuta una aplicación WinForms o WPF y la llamada al código nativo se produce en el hilo de la interfaz de usuario. La razón es que estos dos marcos de interfaz de usuario viven en apartamentos de STA, lo que hace que sea muy difícil (si es posible) que el CLR se desconecte de usted.

Versión corta: si está en una aplicación WinForms o WPF y ejecuta esto en el hilo de la interfaz de usuario, puede asumir un nivel razonable de estabilidad para este identificador.

3

Para lectores futuros: También hay funciones System.Threading.Thread.BeginThreadAffinity()/EndThreadAffinity() que supuestamente impiden que la VM cambie entre diferentes subprocesos físicos. No creo que esto garantice la estabilidad, pero creo que es más probable que sean estables.

3

que puede usar:

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

en lugar de

AppDomain.GetCurrentThreadId()

El problema es sólo para encontrar el número correcto de la rosca si usted tiene más hilos que el hilo principal 0 en ejecución .

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

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

Este funciona en un programa de Windows Forms bastante estándar. Devuelve el mismo ThreadId que AppDomain.GetCurrentThreadId(). Aunque no estoy seguro de si funciona correctamente en fibras como AppDomain.GetCurrentThreadId advierte sobre –

0

uso:

[DllImport ("kernel32.dll")] extern estático uint GetCurrentThreadId();

Cuestiones relacionadas