AppDomain.GetCurrentThreadID против Thread.ManagedThreadID для вызовов API Windows? - PullRequest
15 голосов
/ 21 апреля 2009

Я пытаюсь создать хук для отслеживания текущей позиции курсора мыши. Ничего важного, мне просто нужно было подсчитать несколько пикселей при разработке интерфейса, и я хотел научиться создавать ловушки, поэтому я решил пойти трудным путем, а не вменяемым.

Я нашел пример кода, который объявляет следующую функцию:

 <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 генерирует предупреждение: «Общедоступная общая функция GetCurrentThreadId () As Integer» устарела: «AppDomain.GetCurrentThreadId устарела, поскольку она не обеспечивает стабильный идентификатор, когда управляемые потоки работают на волокнах» нитей). Чтобы получить стабильный идентификатор для управляемого потока, используйте свойство ManagedThreadId в Thread. "

Я пытался использовать ManagedThreadID, но это не работает. Возвращенный идентификатор потока представляется логическим идентификатором потока, так как он выполняется во время выполнения .net, а не идентификатором потока Win32.

Вызов функции ith AppDomain.GetCurrentThreadID работает, но я действительно хотел бы иметь «стабильный идентификатор» для моей нити.

Может ли кто-нибудь объяснить мне, возможно ли использовать ManagedThreadID в этом контексте (я полагаю, нет) и, если нет, то, что мне нужно избегать, чтобы AppDomain.CurrentThreadID не стал «нестабильным»?

Приветствия

Ответы [ 5 ]

14 голосов
/ 21 апреля 2009

Невозможно использовать ManagedThreadId в этом контексте. Это полностью управляемая концепция, которая не имеет реального представительства в родном мире. Следовательно, это не имеет никакого смысла для API, которому вы передаете его.

Причина, по которой существует ManagedThreadId, заключается в том, что необязательно существует соответствие 1-1 между собственным и управляемым потоком. CLR может свободно использовать несколько собственных потоков для запуска одного управляемого потока, если собственный поток совместим с тем, который он заменяет. Это не может быть, например, в другой квартире COM.

В некотором смысле вы немного застряли здесь. AFAIK, нет никакой возможности на 100% гарантировать, что у вас будет тот же собственный поток для данного управляемого потока. Вы можете достичь очень высокого уровня гарантии, хотя, если вы, например, запускаете приложение WinForms или WPF и вызов нативного кода происходит в потоке пользовательского интерфейса. Причина в том, что обе эти структуры пользовательского интерфейса живут в квартирах STA, что делает очень трудным (если вообще возможно) выход из CLR из-под вас.

Короткая версия: Если вы работаете в приложении WinForms или WPF и запускаете его в потоке пользовательского интерфейса, вы можете предположить разумный уровень стабильности для этого идентификатора.

3 голосов
/ 15 февраля 2014
var thread = Process.GetCurrentProcess().Threads.OfType<ProcessThread>().
    SingleOrDefault(x => x.ThreadState == ThreadState.Running);

if (thread != null)
{
    // do stuff here
}
3 голосов
/ 20 мая 2012

Вы можете использовать:

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

вместо

AppDomain.GetCurrentThreadId()

Проблема заключается в том, чтобы найти правильный номер потока, если у вас больше потоков, чем работает основной поток 0.

3 голосов
/ 13 февраля 2010

Для будущих читателей: Существуют также функции System.Threading.Thread.BeginThreadAffinity () / EndThreadAffinity (), которые якобы не позволяют ВМ переключаться между различными физическими потоками. Я не верю, что это гарантирует стабильность, но я думаю, что они, скорее всего, будут стабильными.

1 голос
/ 06 ноября 2015

использование:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...