Apa itu pompa pesan?

104

Di utas ini (diposting sekitar setahun yang lalu) ada diskusi tentang masalah yang bisa datang dengan menjalankan Word dalam sesi non-interaktif. Nasihat (cukup kuat) yang diberikan di sana adalah untuk tidak melakukannya. Dalam satu posting dinyatakan "Office API semua mengasumsikan Anda menjalankan Office dalam sesi interaktif di desktop, dengan monitor, keyboard dan mouse dan, yang paling penting, pompa pesan." Saya tidak yakin apa itu. (Saya telah memprogram di C # hanya sekitar satu tahun; pengalaman pemrograman saya yang lain terutama dengan ColdFusion.)

Memperbarui:

Program saya berjalan melalui sejumlah besar file RTF untuk mengekstrak dua bagian informasi yang digunakan untuk membuat nomor laporan medis. Daripada mencoba dan mencari tahu bagaimana instruksi pemformatan di RTF bekerja, saya memutuskan untuk membukanya di Word dan menarik teks keluar dari sana (tanpa benar-benar memulai GUI). Kadang-kadang, program tersendat di tengah pemrosesan satu file, dan meninggalkan utas Word terbuka yang melekat pada dokumen itu (saya masih harus mencari cara untuk menutupnya). Ketika saya menjalankan ulang program, tentu saja saya mendapat pemberitahuan bahwa ada utas yang menggunakan file itu, dan apakah saya ingin membuka salinan hanya-baca? Ketika saya berkata Ya, Word GUI tiba-tiba muncul entah dari mana dan mulai memproses file. Saya bertanya-tanya mengapa itu terjadi;

Matt Gutting
sumber
3
Mengapa ini ditandai sebagai win32? - Sistem pesan ada di Windows V1 (Yang, seingat saya 8 bit.)
Hogan

Jawaban:

187

Loop pesan adalah sepotong kecil kode yang ada di program Windows asli apa pun. Secara kasar terlihat seperti ini:

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

GetMessage () Win32 API mengambil pesan dari Windows. Program Anda biasanya menghabiskan 99,9% waktunya di sana, menunggu Windows mengatakan sesuatu yang menarik terjadi. TranslateMessage () adalah fungsi pembantu yang menerjemahkan pesan keyboard. DispatchMessage () memastikan bahwa prosedur jendela dipanggil dengan pesan tersebut.

Setiap program .NET berkemampuan GUI memiliki loop pesan, itu dimulai oleh Application.Run ().

Relevansi loop pesan ke Office terkait dengan COM. Program Office adalah program yang mendukung COM, begitulah cara kerja kelas Microsoft.Office.Interop. COM menangani threading atas nama coclass COM, ini memastikan bahwa panggilan yang dibuat pada antarmuka COM selalu dibuat dari utas yang benar. Sebagian besar kelas COM memiliki kunci registri di registri yang menyatakan ThreadingModel mereka, sejauh ini yang paling umum (termasuk Office) menggunakan "Apartemen". Artinya, satu-satunya cara yang aman untuk memanggil metode antarmuka adalah dengan melakukan panggilan dari thread yang sama yang membuat objek kelas. Atau dengan kata lain: sejauh ini sebagian besar kelas COM tidak aman untuk thread.

Setiap utas yang diaktifkan COM milik apartemen COM. Ada dua macam, Apartemen Single Threaded (STA) dan Apartemen Multi Thread (MTA). Kelas COM berulir apartemen harus dibuat pada utas STA. Anda dapat melihat ini kembali di program .NET, titik masuk utas UI dari program Windows Forms atau WPF memiliki atribut [STAThread]. Model apartemen untuk utas lainnya disetel dengan metode Thread.SetApartmentState ().

Sebagian besar pipa Windows tidak akan berfungsi dengan benar jika utas UI bukan STA. Terutama Drag + Drop, clipboard, dialog Windows seperti OpenFileDialog, kontrol seperti WebBrowser, aplikasi Otomasi UI seperti pembaca layar. Dan banyak server COM, seperti Office.

Persyaratan sulit untuk thread STA adalah thread tersebut tidak boleh memblokir dan harus memompa loop pesan. Loop pesan penting karena itulah yang digunakan COM untuk mengatur panggilan metode antarmuka dari satu utas ke utas lainnya. Meskipun .NET membuat panggilan marshaling menjadi mudah (Control.BeginInvoke atau Dispatcher.BeginInvoke misalnya), sebenarnya ini adalah hal yang sangat rumit untuk dilakukan. Utas yang menjalankan panggilan harus dalam keadaan terkenal. Anda tidak bisa secara sewenang-wenang menyela utas dan memaksanya melakukan panggilan metode, yang akan menyebabkan masalah masuk kembali yang mengerikan. Sebuah utas harus "diam", tidak sibuk menjalankan kode apa pun yang mengubah status program.

Mungkin Anda bisa melihat ke mana arahnya: ya, ketika sebuah program menjalankan loop pesan, program itu menganggur. Penyusunan sebenarnya terjadi melalui jendela tersembunyi yang dibuat COM, ia menggunakan PostMessage agar prosedur jendela dari jendela itu mengeksekusi kode. Di utas STA. Loop pesan memastikan bahwa kode ini berjalan.

Hans Passant
sumber
Jawaban yang sangat bagus dan terperinci. Sekadar menambahkan - ada juga STA khusus yang disebut STA utama, yang merupakan STA pertama yang dibuat. Yang idealnya adalah yang dibuat oleh utas UI Anda. STA utama adalah tempat pembuatan komponen dengan model threading = tidak ada. Jika STA utama Anda bukan yang dibuat oleh thread UI Anda - Anda dapat mengalami masalah menarik saat menggunakan kontrol activex lama yang tidak memiliki model threading.
quixver
12

"Pompa pesan" adalah bagian inti dari setiap program Windows yang bertanggung jawab untuk mengirimkan pesan windowing ke berbagai bagian aplikasi. Ini adalah inti dari pemrograman Win32 UI. Karena keberadaannya di mana-mana, banyak aplikasi menggunakan pompa pesan untuk meneruskan pesan di antara modul yang berbeda, itulah sebabnya aplikasi Office akan rusak jika dijalankan tanpa UI apa pun.

Wikipedia memiliki deskripsi dasar .

JSB ձոգչ
sumber
Saya yakin tidak mungkin untuk menulis aplikasi windows tanpa loop pesan, oleh karena itu semua aplikasi menggunakan pompa pesan.
Hogan
2
Anda juga dapat menulis aplikasi GUI sederhana tanpa aplikasi - misalnya, Anda dapat memunculkan kotak pesan tanpa aplikasi Anda sendiri yang memiliki loop pesan di aplikasi Anda.
Jika Anda membuat dialog melalui DialogBox atau DialogBox tidak langsung - Anda tidak memerlukan loop pesan, Anda hanya perlu menyediakan fungsi (dlgproc) yang akan dipanggil oleh windows. (dan kotak pesan hanyalah dialog sederhana)
quixver
6

John berbicara tentang bagaimana sistem Windows (dan sistem berbasis jendela lainnya - X Window , Mac OS asli ....) mengimplementasikan antarmuka pengguna asinkron menggunakan peristiwa melalui sistem pesan.

Di balik layar untuk setiap aplikasi terdapat sistem pesan di mana setiap jendela dapat mengirim acara ke jendela lain atau pendengar acara - ini diimplementasikan dengan menambahkan pesan ke antrian pesan. Ada loop utama yang selalu berjalan melihat antrian pesan ini dan kemudian mengirimkan pesan (atau peristiwa) ke pendengar.

Artikel Wikipedia Message loop di Microsoft Windows menunjukkan contoh kode program Windows dasar - dan seperti yang Anda lihat di tingkat paling dasar, program Windows hanyalah "pompa pesan".

Jadi, untuk menyatukan semuanya. Alasan program windows yang dirancang untuk mendukung UI tidak dapat bertindak sebagai layanan adalah karena program ini membutuhkan loop pesan yang berjalan sepanjang waktu untuk mengaktifkan dukungan UI. Jika Anda menerapkannya sebagai layanan seperti yang dijelaskan, ini tidak akan dapat memproses penanganan peristiwa asinkron internal.

Hogan
sumber
6

Dalam COM , pompa pesan akan melakukan serialisasi dan menonaktifkan pesan yang dikirim antar apartemen. Apartemen adalah proses mini di mana komponen COM dapat dijalankan. Apartemen hadir dalam mode ulir tunggal dan ulir gratis. Apartemen single threaded terutama merupakan sistem warisan untuk aplikasi komponen COM yang tidak mendukung multi-threading. Mereka biasanya digunakan dengan Visual BASIC (karena ini tidak mendukung kode multi-utas) dan aplikasi warisan.

Saya kira bahwa persyaratan pompa pesan untuk Word berasal dari COM API atau bagian dari aplikasi yang tidak aman untuk thread. Ingatlah bahwa model penguliran dan pengumpulan sampah .NET tidak berfungsi baik dengan COM di luar kotak. COM memiliki mekanisme pengumpulan sampah dan model penguliran yang sangat sederhana yang mengharuskan Anda melakukan berbagai hal dengan cara COM. Menggunakan PIA Office standar masih mengharuskan Anda untuk secara eksplisit menutup referensi objek COM, jadi Anda perlu melacak setiap pegangan COM yang dibuat. PIA juga akan membuat barang di belakang layar jika Anda tidak berhati-hati.

Integrasi .NET-COM adalah keseluruhan topik dengan sendirinya, dan bahkan ada buku yang ditulis tentang subjek tersebut. Bahkan menggunakan COM API untuk Office dari aplikasi desktop interaktif mengharuskan Anda untuk melewati rintangan dan memastikan bahwa referensi dirilis secara eksplisit.

Office dapat dianggap tidak aman untuk utas, jadi Anda memerlukan contoh Word, Excel , atau aplikasi Office lain yang terpisah untuk setiap utas. Anda harus menanggung overhead awal atau mempertahankan kumpulan utas. Kumpulan utas harus diuji dengan cermat untuk memastikan semua referensi COM dirilis dengan benar. Bahkan memulai dan mematikan instans mengharuskan Anda untuk memastikan semua referensi dirilis dengan benar. Kegagalan menandai i dan melewati t Anda di sini akan mengakibatkan sejumlah besar objek COM yang mati dan bahkan seluruh contoh Word yang sedang berjalan bocor.

ConcernedOfTunbridgeWells
sumber
1
Ada beberapa ketidakakuratan dalam jawaban Anda. Ada 3 jenis appartments - STA (Single threaded), MTA (Multi Threaded) dan NTA (Neutral Threaded). Utas gratis digunakan untuk mendeskripsikan komponen yang mengumpulkan marshaller berulir gratis, tidak ada yang namanya apartemen berulir gratis. COM menggunakan pesan untuk berkomunikasi dengan STA. Untuk komponen yang hidup dalam MTA (atau yang menggabungkan marshaller berulir gratis) tidak diperlukan loop pesan. AFAIK - lpc digunakan untuk mengatur data dari utas pemanggil ke utas dari kumpulan utas RPC yang kemudian benar-benar memanggil metode tersebut.
quixver
0

Menurut saya diskusi Channel 9 ini memiliki penjelasan singkat yang bagus:

Proses komunikasi jendela ini dimungkinkan oleh apa yang disebut Pompa Pesan Windows. Pikirkan Message Pump sebagai entitas yang memungkinkan kerja sama antara jendela aplikasi dan desktop.

Richard Ev
sumber
2
wow ... itu adalah kutipan yang mengerikan dan menyesatkan. (Sebuah "entitas"? Err .. tidak.)
Hogan
4
entitas - objek: sesuatu yang ada sebagai atau dianggap sebagai objek tunggal yang terpisah encarta.msn.com/dictionary_1861608661/entity.html
Matthew Whited