2009-04-21 7 views
15

J'essaie de créer un crochet pour surveiller la position actuelle du curseur de la souris. Rien d'important, j'ai juste besoin de compter quelques pixels lors de la conception de l'interface et je voulais apprendre comment créer un crochet, alors j'ai décidé d'y aller à la dure plutôt que de manière saine.AppDomain.GetCurrentThreadID vs Thread.ManagedThreadID pour les appels d'API Windows?

J'ai trouvé un exemple de code qui déclare la fonction suivante:

<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 

Lorsque la fonction est appelée, le code suivant est utilisé:

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

Mais Appdomain.GetCurrentThreadID génère l'avertissement: '' Fonction publique partagée GetCurrentThreadId() As Integer 'est obsolète:' AppDomain.GetCurrentThreadId est obsolète car il ne fournit pas d'ID stable lorsque les threads gérés s'exécutent sur des fibres (également appelés threads légers). th read, utilisez la propriété ManagedThreadId sur Thread. "

J'ai essayé d'utiliser ManagedThreadID, mais cela ne fonctionne pas. L'ID de thread retourné semble être l'ID de thread logique du thread, car il s'exécute dans l'exécution .net, plutôt que l'identificateur de thread Win32.

Appel de la fonction avec AppDomain.GetCurrentThreadID fonctionne, mais j'aimerais vraiment avoir un "identifiant stable" pour mon thread. Est-ce que quelqu'un peut m'expliquer s'il est possible d'utiliser ManagedThreadID dans ce contexte (je suppose que non) et, sinon, les choses que je dois éviter afin d'empêcher que AppDomain.CurrentThreadID devienne "instable"?

Vive

+0

Curieux de savoir si vous avez trouvé une solution de contournement pour ce problème? – amadib

+0

Pas vraiment, non. J'ai fondamentalement juste pris le mot de JaredPar pour que le threadID soit raisonnablement stable, utilisé ceci pendant le test, et ai ensuite changé l'interface pour réagir aux événements OnMouseMove au lieu du déploiement final. Je ne l'ai pas fait à l'origine parce que cela signifie passer des événements à travers toute une chaîne de contrôles et est généralement juste une douleur dans le cul. Il est cependant plus fiable que la méthode ci-dessus, qui n'a échoué qu'une ou deux fois pendant toute la durée du test, mais a échoué. – Frosty840

Répondre

13

Il est impossible d'utiliser ManagedThreadId dans ce contexte. C'est un concept entièrement géré et n'a aucune représentation réelle dans le monde natal. Par conséquent, cela n'a aucun sens pour les API que vous transmettez.

La raison pour laquelle ManagedThreadId existe est parce qu'il n'y a pas nécessairement un mappage 1-1 entre un thread natif et géré. Le CLR est libre d'utiliser plusieurs threads natifs pour exécuter un thread géré unique tant que le thread natif est compatible avec celui qu'il remplace. Il ne peut pas, par exemple, être dans un appartement COM différent.

D'une certaine manière, vous êtes un peu coincé ici. AFAIK, il n'y a aucun moyen de garantir à 100% que vous aurez le même thread natif pour un thread géré donné. Vous pouvez obtenir un très haut niveau de garantie si, par exemple, vous exécutez une application WinForms ou WPF et que l'appel au code natif se produit sur le thread de l'interface utilisateur. La raison en est que ces deux frameworks UI vivent dans des appartements STA, ce qui rend très difficile (voire possible) le passage du CLR sous vous.

Version abrégée: Si vous utilisez une application WinForms ou WPF et que vous l'exécutez sur le thread d'interface utilisateur, vous pouvez supposer un niveau de stabilité raisonnable pour cet identificateur.

3

Pour les futurs lecteurs: Il existe également des fonctions System.Threading.Thread.BeginThreadAffinity()/EndThreadAffinity() qui empêchent la machine virtuelle de basculer entre différents threads physiques. Je ne crois pas que ceux-ci garantissent la stabilité, mais je pense qu'ils sont plus susceptibles d'être stables.

3

Vous pouvez utiliser:

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

au lieu de

AppDomain.GetCurrentThreadId()

Le problème est que pour trouver le nombre correct du fil si vous avez plus de threads que le thread principal 0 fonctionnement .

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

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

Celui-ci fonctionne dans un programme Windows Forms assez standard. Il renvoie le même ThreadId que AppDomain.GetCurrentThreadId(). Pas sûr cependant si cela fonctionne correctement sur les fibres comme AppDomain.GetCurrentThreadId met en garde à propos de –

0

utilisation:

[DllImport ("kernel32.dll")] de extern statique uint GetCurrentThreadId();

Questions connexes