메시지 펌프 란?


103

에서 이 스레드 (년 전에 게시) 비 대화식 세션에서 Word를 실행에 올 수있는 문제에 대한 논의가있다. 거기에 주어진 (아주 강한) 충고는 그렇게하지 말라는 것입니다. 한 게시물에서 "Office API는 모두 데스크톱에서 모니터, 키보드, 마우스 및 가장 중요한 메시지 펌프를 사용하는 대화 형 세션에서 Office를 실행한다고 가정합니다." 그게 뭔지 모르겠어요. (저는 약 1 년 동안 C #으로 프로그래밍 해 왔으며 다른 프로그래밍 경험은 주로 ColdFusion에서 경험했습니다.)

최신 정보:

내 프로그램은 많은 수의 RTF 파일을 통해 의료 보고서 번호를 구성하는 데 사용되는 두 가지 정보를 추출합니다. RTF의 형식 지정 지침이 어떻게 작동하는지 알아 내기보다는 Word에서 열어 텍스트를 꺼내기로 결정했습니다 (실제로 GUI를 시작하지 않음). 때때로 프로그램은 하나의 파일을 처리하는 도중에 문제가 발생하여 해당 문서에 첨부 된 Word 스레드를 열어 두었습니다 (아직도 파일을 종료하는 방법을 알아 내야합니다). 프로그램을 다시 실행하면 당연히 해당 파일을 사용하는 스레드가 있다는 알림을 받았으며 읽기 전용 복사본을 열고 싶었습니까? 예라고 말했을 때 갑자기 Word GUI가 갑자기 나타나서 파일 처리를 시작했습니다. 왜 그런 일이 일어 났는지 궁금합니다.


3
왜 이것이 win32로 태그가 지정됩니까? -메시지 시스템은 Windows V1 (내가 기억하는 것처럼 8 비트였습니다.)
Hogan

답변:


186

메시지 루프는 모든 기본 Windows 프로그램에 존재하는 작은 코드 조각입니다. 대략 다음과 같습니다.

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{ 
   TranslateMessage(&msg); 
   DispatchMessage(&msg); 
} 

GetMessage () Win32 API는 Windows에서 메시지를 검색합니다. 프로그램은 일반적으로 Windows에서 흥미로운 일이 발생했음을 알리는 데 99.9 %의 시간을 보냅니다. TranslateMessage ()는 키보드 메시지를 번역하는 도우미 함수입니다. DispatchMessage ()는 창 프로 시저가 메시지와 함께 호출되도록합니다.

모든 GUI 사용 .NET 프로그램에는 메시지 루프가 있으며 Application.Run ()에 의해 시작됩니다.

Office에 대한 메시지 루프의 관련성은 COM과 관련이 있습니다. Office 프로그램은 COM 사용 가능 프로그램이므로 Microsoft.Office.Interop 클래스가 작동합니다. COM은 COM coclass를 대신하여 스레딩을 처리하며 COM 인터페이스에 대한 호출이 항상 올바른 스레드에서 이루어 지도록합니다. 대부분의 COM 클래스는 ThreadingModel을 선언하는 레지스트리 키를 레지스트리에 가지고 있으며, 가장 일반적인 클래스 (Office 포함)는 "Apartment"를 사용합니다. 즉, 인터페이스 메서드를 호출하는 유일한 안전한 방법은 클래스 개체를 만든 동일한 스레드에서 호출하는 것입니다. 또는 다른 말로하면 대부분의 COM 클래스는 스레드로부터 안전하지 않습니다.

모든 COM 사용 스레드는 COM 아파트에 속합니다. STA (Single Threaded Apartments)와 MTA (Multi Thread Apartment)의 두 가지 종류가 있습니다. 아파트 스레드 COM 클래스는 STA 스레드에서 만들어야합니다. .NET 프로그램에서 다시 볼 수 있습니다. Windows Forms 또는 WPF 프로그램의 UI 스레드 진입 점에는 [STAThread] 특성이 있습니다. 다른 스레드에 대한 아파트 모델은 Thread.SetApartmentState () 메서드에 의해 설정됩니다.

UI 스레드가 STA가 아닌 경우 Windows 배관의 많은 부분이 제대로 작동하지 않습니다. 특히 Drag + Drop, 클립 보드, OpenFileDialog와 같은 Windows 대화 상자, WebBrowser와 같은 컨트롤, 화면 판독기와 같은 UI 자동화 앱이 있습니다. 그리고 Office와 같은 많은 COM 서버.

STA 스레드에 대한 엄격한 요구 사항은 차단하지 않아야하고 메시지 루프를 펌핑해야한다는 것입니다. 메시지 루프는 COM이 한 스레드에서 다른 스레드로 인터페이스 메서드 호출을 마샬링하는 데 사용하기 때문에 중요합니다. .NET을 사용하면 마샬링 호출이 쉬워 지지만 (예 : Control.BeginInvoke 또는 Dispatcher.BeginInvoke) 실제로 수행하기 매우 까다로운 작업입니다. 호출을 실행하는 스레드는 잘 알려진 상태 여야합니다. 스레드를 임의로 인터럽트하고 메서드 호출을 강제 할 수는 없습니다. 이는 끔찍한 재진입 문제를 유발할 수 있습니다. 스레드는 프로그램 상태를 변경하는 코드를 실행 하느라 바쁘지 않고 "유휴"상태 여야합니다.

아마도 그것이 어디로 이끄는지를 볼 수있을 것입니다. 예, 프로그램이 메시지 루프를 실행할 때 그것은 유휴 상태입니다. 실제 마샬링은 COM이 만든 숨겨진 창을 통해 발생하며 PostMessage를 사용하여 해당 창의 창 프로 시저가 코드를 실행하도록합니다. STA 스레드에서. 메시지 루프는이 코드가 실행되도록합니다.


아주 좋고 자세한 답변. 추가하기 만하면됩니다. 메인 STA라는 특수 STA도 있는데, 이는 처음으로 생성 된 STA입니다. 이상적으로는 UI 스레드에 의해 생성 된 것이어야합니다. 주 STA는 스레딩 모델이없는 구성 요소가 생성되는 곳입니다. 주 STA가 UI 스레드에 의해 생성 된 것이 아닌 경우 스레딩 모델이없는 이전 ActiveX 컨트롤을 사용할 때 흥미로운 문제가 발생할 수 있습니다.
quixver

12

"메시지 펌프"는 응용 프로그램의 다양한 부분에 윈도우 메시지를 발송하는 역할을하는 모든 Windows 프로그램의 핵심 부분입니다. 이것이 Win32 UI 프로그래밍의 핵심입니다. 편재성 때문에 많은 응용 프로그램이 메시지 펌프를 사용하여 서로 다른 모듈간에 메시지를 전달하기 때문에 UI없이 실행하면 Office 응용 프로그램이 중단됩니다.

Wikipedia에는 기본적인 설명이 있습니다.


메시지 루프없이 Windows 앱을 작성하는 것은 불가능하다고 생각하므로 모든 애플리케이션이 메시지 펌프를 사용합니다.
Hogan

2
하나없이 간단한 GUI 앱을 작성할 수도 있습니다. 예를 들어 앱에 메시지 루프가없는 앱없이 메시지 상자를 팝업 할 수 있습니다.

DialogBox 또는 DialogBox를 통해 간접적으로 대화 상자를 만드는 경우-메시지 루프가 필요하지 않으며 Windows에서 호출 할 함수 (dlgproc) 만 제공하면됩니다. (메시지 상자는 단순한 대화 상자입니다.)
quixver

6

John은 Windows 시스템 (및 기타 창 기반 시스템 -X Window , 원래 Mac OS ....)이 메시지 시스템을 통해 이벤트를 사용하여 비동기 사용자 인터페이스를 구현 하는 방법에 대해 이야기하고 있습니다.

각 애플리케이션의이면에는 각 창이 다른 창이나 이벤트 리스너에 이벤트를 보낼 수있는 메시징 시스템이 있습니다. 이는 메시지 대기열에 메시지를 추가하여 구현됩니다. 항상이 메시지 큐를보고 리스너에게 메시지 (또는 이벤트)를 전달하는 메인 루프가 있습니다.

Wikipedia 기사 Microsoft Windows의 메시지 루프 는 기본 Windows 프로그램의 예제 코드를 보여줍니다. 가장 기본적인 수준에서 볼 수 있듯이 Windows 프로그램은 "메시지 펌프"일뿐입니다.

그래서 그것을 모두 모으십시오. UI를 지원하도록 설계된 Windows 프로그램이 서비스 역할을 할 수없는 이유는 UI 지원을 활성화하기 위해 항상 실행되는 메시지 루프가 필요하기 때문입니다. 설명 된대로 서비스로 구현하면 내부 비동기 이벤트 처리를 처리 할 수 ​​없습니다.


6

에서 COM 메시지 펌프 serialises와 드 serialises 메시지는 아파트 사이에 전송. 아파트는 COM 구성 요소를 실행할 수있는 미니 프로세스입니다. 아파트는 단일 스레드 및 자유 스레드 모드로 제공됩니다. 단일 스레드 아파트는 주로 다중 스레드를 지원하지 않는 COM 구성 요소의 응용 프로그램을위한 레거시 시스템입니다. 일반적으로 Visual BASIC (멀티 스레드 코드를 지원하지 않았기 때문에) 및 레거시 애플리케이션과 함께 사용되었습니다.

Word에 대한 메시지 펌프 요구 사항 은 COM API 또는 스레드로부터 안전하지 않은 응용 프로그램의 일부에서 비롯된 것 같습니다. 명심 .NET 스레딩 및 쓰레기 수거 모델은 상자의 COM과 좋게 재생되지 않습니다. COM에는 COM 방식으로 작업을 수행해야하는 매우 단순한 가비지 수집 메커니즘과 스레딩 모델이 있습니다. 표준 Office PIA를 사용하려면 COM 개체 참조를 명시 적으로 종료해야하므로 생성 된 모든 COM 핸들을 추적해야합니다. PIA는 또한 조심하지 않으면 장면 뒤에서 물건을 만들 것입니다.

.NET-COM 통합은 그 자체로 전체 주제이며 주제에 대한 책도 있습니다. 대화 형 데스크톱 응용 프로그램에서 Office 용 COM API를 사용하는 경우에도 다음 단계를 거쳐 참조가 명시 적으로 해제되었는지 확인해야합니다.

Office는 스레드에 안전하지 않은 것으로 간주 될 수 있으므로 각 스레드에 대해 별도의 Word, Excel 또는 기타 Office 응용 프로그램 인스턴스가 필요합니다 . 시작 오버 헤드가 발생하거나 스레드 풀을 유지해야합니다. 모든 COM 참조가 올바르게 해제되었는지 확인하려면 스레드 풀을 꼼꼼하게 테스트해야합니다. 인스턴스를 시작하고 종료하는 경우에도 모든 참조가 올바르게 해제되었는지 확인해야합니다. 당신의 i를 점하고 여기에 t를 교차하지 않으면 많은 수의 죽은 COM 개체가 발생하고 Word의 전체 실행 인스턴스가 유출됩니다.


1
귀하의 답변에 몇 가지 부정확 한 내용이 있습니다. 아파트에는 STA (단일 스레드), MTA (다중 스레드) 및 NTA (중립 스레드)의 3 가지 유형이 있습니다. 자유 스레드는 자유 스레드 마샬 러를 집계하는 구성 요소를 설명하는 데 사용되며 자유 스레드 아파트와 같은 것은 없습니다. COM은 메시지를 사용하여 STA와 통신합니다. MTA (또는 자유 스레드 마샬 러를 집계하는)에있는 구성 요소의 경우 메시지 루프가 필요하지 않습니다. AFAIK-lpc는 호출 스레드에서 실제로 메서드를 호출하는 RPC 스레드 풀의 스레드로 데이터를 마샬링하는 데 사용됩니다.
quixver


0

이 채널 9 토론에 간결한 설명 있다고 생각합니다 .

이 창 통신 프로세스는 소위 Windows 메시지 펌프로 가능합니다. Message Pump를 응용 프로그램 창과 데스크탑 간의 협력을 가능하게하는 엔티티로 생각하십시오.


2
와 ... 그건 끔찍하고 오해의 소지가있는 인용구입니다. ( "엔티티"? Err .. no.)
Hogan

4
entity-object : 존재하거나 하나의 개별 객체로 인식되는 것 encarta.msn.com/dictionary_1861608661/entity.html
Matthew Whited
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.