Single-Threaded 아파트먼트

단일 스레드 아파트(아파트 모델 프로세스)를 사용하면 동시에 실행되는 여러 개체를 처리하기 위한 메시지 기반 패러다임을 제공합니다. 이를 통해 스레드를 허용하여 보다 효율적인 코드를 작성할 수 있지만 시간이 많이 걸리는 작업이 완료될 때까지 대기하여 다른 스레드를 실행할 수 있습니다.

아파트 모델 프로세스로 초기화되고 창 메시지를 검색하고 디스패치하는 프로세스의 각 스레드는 단일 스레드 아파트 스레드입니다. 각 스레드는 자체 아파트 내에 있습니다. 아파트 내에서 인터페이스 포인터는 마샬링하지 않고 전달할 수 있으므로 단일 스레드 아파트 스레드의 모든 개체가 직접 통신합니다.

모두 동일한 스레드에서 실행되므로 동기 실행이 있어야 하는 관련 개체의 논리적 그룹화는 동일한 단일 스레드 아파트 스레드에 있을 수 있습니다. 그러나 아파트 모델 개체는 둘 이상의 스레드에 상주할 수 없습니다. 다른 스레드의 개체에 대한 호출은 소유 스레드의 컨텍스트 내에서 이루어져야 하므로 분산 COM은 프록시에서 를 호출할 때 자동으로 스레드를 전환합니다.

프로세스 간 및 스레드 간 모델은 비슷합니다. 동일한 프로세스 내의 다른 아파트(다른 스레드)에 있는 개체에 인터페이스 포인터를 전달해야 하는 경우 다른 프로세스의 개체가 프로세스 경계를 넘어 포인터를 전달하는 데 사용하는 것과 동일한 마샬링 모델을 사용합니다. 표준 마샬링 개체에 대한 포인터를 가져오면 프로세스 간에 수행하는 것과 동일한 방식으로 스레드 경계(아파트 간)를 넘어 인터페이스 포인터를 마샬링할 수 있습니다. (아파트 간에 전달될 때 인터페이스 포인터를 마샬링해야 합니다.)

단일 스레드 아파트에 대한 규칙은 간단하지만 신중하게 따르는 것이 중요합니다.

  • 모든 개체는 하나의 스레드(단일 스레드 아파트 내)에만 있어야 합니다.
  • 각 스레드에 대한 COM 라이브러리를 초기화합니다.
  • 아파트 간에 개체를 전달할 때 개체에 대한 모든 포인터를 마샬링합니다.
  • 각 단일 스레드 아파트는 동일한 프로세스 내에서 다른 프로세스 및 아파트의 호출을 처리하는 메시지 루프가 있어야 합니다. 개체가 없는 단일 스레드 아파트(클라이언트 전용)도 일부 애플리케이션에서 사용하는 브로드캐스트 메시지를 디스패치하는 메시지 루프가 필요합니다.
  • DLL 기반 또는 In-process 개체는 COM 초기화 함수를 호출하지 않습니다. 대신, 레지스트리의 InprocServer32 키 아래에 ThreadingModel 명명된 값으로 스레딩 모델을 등록합니다. 아파트 인식 개체는 DLL 진입점도 신중하게 작성해야 합니다. 스레딩 In-Process 서버에 적용되는 특별한 고려 사항이 있습니다. 자세한 내용은 In-Process 서버 스레딩 문제를 참조하세요.

여러 개체가 단일 스레드에 상주할 수 있지만 아파트 모델 개체는 둘 이상의 스레드에 살 수 없습니다.

클라이언트 프로세스 또는 out-of-process 서버의 각 스레드는 CoInitialize를 호출하거나 CoInitializeEx를 호출하고 dwCoInit 매개 변수에 대한 COINIT_APARTMENTTHREADED 지정해야 합니다. 기본 아파트는 CoInitializeEx를 먼저 호출하는 스레드입니다. In-Process 서버에 대한 자세한 내용은 In-Process 서버 스레딩 문제를 참조하세요.

개체에 대한 모든 호출은 해당 스레드(아파트 내)에서 이루어져야 합니다. 다른 스레드에서 직접 개체를 호출하는 것은 금지되어 있습니다. 이러한 자유 스레드 방식으로 개체를 사용하면 애플리케이션에 문제가 발생할 수 있습니다. 이 규칙의 의미는 아파트 간에 전달될 때 개체에 대한 모든 포인터를 마샬링해야 한다는 것입니다. COM은 이 목적을 위해 다음과 같은 두 가지 함수를 제공합니다.

이러한 함수는 MSHCTX_INPROC 플래그를 사용해야 하는 CoMarshalInterfaceCoUnmarshalInterface 함수에 대한 호출을 래핑합니다.

일반적으로 마샬링이 COM에 의해 자동으로 수행됩니다. 예를 들어 인터페이스 포인터를 다른 아파트의 개체에 대한 프록시 호출의 메서드 호출에서 매개 변수로 전달하거나 CoCreateInstance를 호출할 때 COM은 자동으로 마샬링을 수행합니다. 그러나 애플리케이션 작성기가 일반 COM 메커니즘을 사용하지 않고 아파트 간에 인터페이스 포인터를 전달하는 특별한 경우 작성기는 마샬링을 수동으로 처리해야 합니다.

프로세스의 한 아파트(아파트 1)에 인터페이스 포인터가 있고 다른 아파트(아파트 2)를 사용해야 하는 경우 Apartment 1은 CoMarshalInterThreadInterfaceInStream 을 호출하여 인터페이스를 마샬링해야 합니다. 이 함수에서 만든 스트림은 스레드로부터 안전하며 Apartment 2에서 액세스할 수 있는 변수에 저장되어야 합니다. 아파트 2는 인터페이스를 숨기려면 CoGetInterfaceAndReleaseStream 에 이 스트림을 전달해야 하며 인터페이스에 액세스할 수 있는 프록시에 대한 포인터를 다시 가져옵니다. 클라이언트가 모든 COM 작업을 완료할 때까지 기본 아파트는 활성 상태로 유지되어야 합니다(In-Process 서버 스레딩 문제에 설명된 대로 일부 in-process 개체가 기본 아파트에 로드되기 때문). 이러한 방식으로 스레드 간에 하나의 개체를 전달한 후에는 인터페이스 포인터를 매개 변수로 전달하기가 매우 쉽습니다. 이렇게 하면 분산 COM은 애플리케이션에 대한 마샬링 및 스레드 전환을 수행합니다.

동일한 프로세스 내에서 다른 프로세스 및 아파트의 호출을 처리하려면 각 단일 스레드 아파트에 메시지 루프가 있어야 합니다. 즉, 스레드의 작업 함수에는 GetMessage/DispatchMessage 루프가 있어야 합니다. 다른 동기화 기본 형식을 사용하여 스레드 간에 통신하는 경우 MsgWaitForMultipleObjects 함수를 사용하여 메시지와 스레드 동기화 이벤트를 모두 대기할 수 있습니다. 이 함수에 대한 설명서에는 이러한 종류의 조합 루프의 예가 있습니다.

COM은 각 단일 스레드 아파트의 Windows 클래스 "OleMainThreadWndClass"를 사용하여 숨겨진 창을 만듭니다. 개체에 대한 호출은 이 숨겨진 창에 대한 창 메시지로 수신됩니다. 개체의 아파트가 메시지를 검색하고 디스패치하면 숨겨진 창에서 메시지를 수신합니다. 창 프로시저는 개체의 해당 인터페이스 메서드를 호출합니다.

여러 클라이언트가 개체를 호출하면 호출이 메시지 큐에 큐에 대기되고 해당 아파트가 메시지를 검색하고 디스패치할 때마다 개체가 호출을 받습니다. 호출은 COM에 의해 동기화되고 호출은 항상 개체의 아파트에 속한 스레드에 의해 전달되므로 개체의 인터페이스 구현은 동기화를 제공할 필요가 없습니다. 단일 스레드 아파트는 IMessageFilter를 구현하여 필요할 때 전화를 취소하거나 창 메시지를 받을 수 있도록 허용할 수 있습니다.

인터페이스 메서드 구현 중 하나가 메시지를 검색하고 디스패치하거나 다른 스레드에 ORPC 호출을 실행하여 다른 호출이 개체에 전달되도록 하는 경우 개체를 다시 입력할 수 있습니다(동일한 아파트). OLE는 동일한 스레드에서 재진입을 방지하지는 않지만 스레드 안전을 제공하는 데 도움이 될 수 있습니다. 이는 메시지를 처리하는 동안 메시지를 검색하고 디스패치하는 경우 창 프로시저를 다시 입력할 수 있는 방법과 동일합니다. 그러나 다른 단일 스레드 아파트 서버를 호출하는 Out-of-process 단일 스레드 아파트 서버를 호출하면 첫 번째 서버를 다시 입력할 수 있습니다.

아파트 간 인터페이스 액세스

스레딩 모델 선택

다중 스레드 아파트먼트

In-Process 서버 스레딩 문제

프로세스, 스레드 및 아파트

단일 스레드 및 다중 스레드 통신