나는 이것을 사용하여 버그를 수정했습니다.
_Thread.SetApartmentState(ApartmentState.STA);
이제 그 의미와 작동 이유를 이해하고 싶습니다!
답변
COM은 .NET의 원조입니다. 그들은 그것에 대해 꽤 높은 목표를 가지고 있었는데, COM이하는 일 중 하나는 .NET이 완전히 건너 뛰는 것 중 하나는 클래스에 대한 스레딩 보장을 제공하는 것입니다. COM 클래스는 어떤 종류의 스레딩 요구 사항이 있는지 게시 할 수 있습니다. 그리고 COM 인프라는 이러한 요구 사항이 충족되는지 확인합니다.
이것은 .NET에는 전혀 없습니다. 예를 들어 여러 스레드에서 Queue <> 개체를 사용할 수 있지만 제대로 잠그지 않으면 코드에 진단하기 매우 어려운 버그가 생깁니다.
COM 스레딩의 정확한 세부 사항이 너무 커서 게시물에 맞지 않습니다. 질문의 세부 사항에 초점을 맞출 것입니다. COM 개체를 만드는 스레드는 스레드 옵션이 제한된 COM 클래스에 제공 할 지원 유형을 COM에 알려야합니다. 이러한 클래스의 대부분은 소위 아파트 스레딩 만 지원하며 해당 인터페이스 메서드는 인스턴스를 만든 동일한 스레드에서만 안전하게 호출 할 수 있습니다. 즉, “나는 스레딩을 지원하지 않습니다 . 잘못된 스레드에서 나를 절대 호출 하지 않도록주의하십시오”라고 발표 합니다. 심지어 클라이언트 코드가 실제로 경우 않는 다른 스레드에서 호출.
STA (Single Threaded Apartment)와 MTA의 두 종류가 있습니다. 이는 COM으로 모든 작업을 수행하는 스레드에서 호출해야하는 함수 인 CoInitializeEx () 호출에 지정됩니다. CLR은 스레드를 시작할 때마다 자동으로 해당 호출을 수행합니다. 프로그램의 기본 시작 스레드의 경우 Main () 메서드의 [STAThread] 또는 [MTAThread] 속성에서 전달할 값을 가져옵니다. 기본값은 MTA입니다. 직접 만든 스레드의 경우 SetApartmentState ()에 대한 호출에 의해 결정됩니다. 기본값은 MTA입니다. 스레드 풀 스레드는 항상 MTA이며 변경할 수 없습니다.
Windows에는 STA가 필요한 코드가 많이 있습니다. 사용자가 직접 사용하는 주목할만한 예는 클립 보드, 드래그 + 드롭 및 셸 대화 상자 (예 : OpenFileDialog)입니다. UI 자동화 프로그램 및 메시지 관찰 후크와 같이 볼 수없는 많은 코드가 있습니다. 그 코드 중 어느 것도 스레드로부터 안전 할 필요는 없으며, 작성자는 어떤 프로그램에서 사용되는지 알지 못한 채 안전하게 만드는 데 매우 어려울 것입니다. 따라서 WPF 또는 Windows Forms 프로젝트의 UI 스레드는 창을 만드는 모든 스레드와 마찬가지로 이러한 코드를 지원하려면 항상 STA 여야합니다.
당신이 당신의 스레드가 STA 그러나 것을 COM에 할 약속 않는 단일 스레드 아파트 계약을 따르도록 요구합니다. 그들은 매우 뻣뻣하고 계약을 어길 때 문제를 진단하기가 까다로울 수 있습니다. 요구 사항은 일정 시간 동안 스레드를 차단하지 않고 메시지 루프를 펌핑하는 것입니다. 후자의 요구 사항은 WPF 또는 Winforms의 UI 스레드에 의해 충족되지만 자체 STA 스레드를 생성하는 경우 직접 처리해야합니다. 계약 위반에 대한 일반적인 진단은 교착 상태입니다.
이러한 요구 사항을 지원하기 위해 CLR에 내장 된 많은 지원이있어 문제를 방지 할 수 있습니다. 잠금 문과 WaitOne ()이 메소드는 메시지 루프를 펌프 할 때 STA 스레드에서 차단합니다. 그러나 이것은 차단되지 않는 요구 사항 만 처리하므로 여전히 고유 한 메시지 루프를 만들어야합니다. WPF 및 Winforms 모두에서 Application.Run ().
이전에 COM을 행복하게 유지하기 위해 메시지 루프를 갖는 것의 중요성에 대한 자세한 내용이 포함 된 답변을 제공했습니다. 여기 에서 게시물을 찾을 수 있습니다 .