StaTaskScheduler 및 STA 스레드 메시지 펌핑
Parallel 팀의 ParallelExtensionsExtras에 있는 StaTaskScheduler는 타사에서 제공하는 레거시 STA COM 개체를 호스팅하도록 설계되었습니다. 구현 설명에는 MTA 및 STA 스레드를 지원하고 WaitHandle.WaitAll과 같은 기본 API의 차이점을 처리한다고 명시되어 있습니다.
그러나 StaTaskScheduler가 STA 스레드의 교착 상태를 방지하기 위해 메시지를 펌프하는 대기 API(예: CoWaitForMultipleHandles)를 사용한다고 가정하는 것은 올바르지 않습니다. TPL의 차단 부분이 메시지를 펌프하지 않아 교착 상태가 발생할 수 있습니다.
간단한 시나리오에서는 프로세스 내 STA COM 개체 A가 프로세스 외 개체 B를 호출하고 B로부터 콜백을 받을 것으로 예상할 때 문제가 발생합니다. BlockingCollection
해결책은 CoWaitForMultipleHandles를 사용하여 메시지를 명시적으로 펌핑하는 사용자 정의 동기화 컨텍스트를 구현하고 StaTaskScheduler에 의해 시작된 모든 STA 스레드에 이를 설치하는 것입니다.
MsgWaitForMultipleObjectsEx는 CoWaitForMultipleHandles보다 메시지 펌핑에 더 적합합니다. 사용자 지정 동기화 컨텍스트의 Wait 메서드는SynchronizationContext.WaitHelper에 대한 전달자로 구현되거나 완전한 기능을 갖춘 메시지 펌핑 루프를 포함할 수 있습니다.
다음 코드는 메시지 펌핑 루프를 포함하는 사용자 정의 동기화 컨텍스트 구현을 보여줍니다.
<code class="language-c#">// 核心循环 var msg = new NativeMethods.MSG(); while (true) { // 带有 MWMO_INPUTAVAILABLE 的 MsgWaitForMultipleObjectsEx 返回, // 即使消息队列中已经看到但未删除消息 nativeResult = NativeMethods.MsgWaitForMultipleObjectsEx( count, waitHandles, (uint)remainingTimeout, QS_MASK, NativeMethods.MWMO_INPUTAVAILABLE); if (IsNativeWaitSuccessful(count, nativeResult, out managedResult) || WaitHandle.WaitTimeout == managedResult) return managedResult; // 有消息,泵送并分派它 if (NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, NativeMethods.PM_REMOVE)) { NativeMethods.TranslateMessage(ref msg); NativeMethods.DispatchMessage(ref msg); } if (hasTimedOut()) return WaitHandle.WaitTimeout; }</code>
이 사용자 정의 동기화 컨텍스트 및 메시지 펌핑 루프를 사용하면 STA 스레드에서 차단 대기를 사용하는 경우에도 메시지가 펌핑되고 STA 스레드 교착 상태가 방지됩니다.
위 내용은 차단 대기와 함께 StaTaskScheduler를 사용할 때 STA 스레드에서 교착 상태를 어떻게 방지할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!