ปั๊มข้อความคืออะไร?


104

ในชุดข้อความนี้ (โพสต์เมื่อประมาณหนึ่งปีที่แล้ว) มีการอภิปรายเกี่ยวกับปัญหาที่อาจมาพร้อมกับการรัน Word ในเซสชันที่ไม่โต้ตอบ คำแนะนำ (ค่อนข้างรัดกุม) ที่ให้ไว้นั้นไม่ควรทำเช่นนั้น ในโพสต์หนึ่งมีการระบุว่า "Office API ทั้งหมดถือว่าคุณใช้งาน Office ในเซสชันแบบโต้ตอบบนเดสก์ท็อปด้วยจอภาพแป้นพิมพ์และเมาส์และที่สำคัญที่สุดคือปั๊มข้อความ" ฉันไม่แน่ใจว่ามันคืออะไร (ฉันเขียนโปรแกรมใน C # มาได้ประมาณหนึ่งปีเท่านั้นประสบการณ์การเขียนโปรแกรมอื่น ๆ ของฉันส่วนใหญ่มาจาก ColdFusion)

อัปเดต:

โปรแกรมของฉันทำงานผ่านไฟล์ RTF จำนวนมากเพื่อดึงข้อมูลสองส่วนที่ใช้สร้างหมายเลขรายงานทางการแพทย์ แทนที่จะลองดูว่าคำแนะนำการจัดรูปแบบใน RTF ทำงานอย่างไรฉันตัดสินใจเปิดใน Word และดึงข้อความออกจากที่นั่น (โดยไม่ต้องเริ่ม GUI จริง ๆ ) ในบางครั้งโปรแกรมเกิดอาการสะอึกระหว่างการประมวลผลไฟล์เดียวและเปิดเธรด Word ที่แนบมากับเอกสารนั้นทิ้งไว้ (ฉันยังต้องหาวิธีปิดไฟล์นั้น) เมื่อฉันรันโปรแกรมอีกครั้งแน่นอนว่าฉันได้รับการแจ้งเตือนว่ามีเธรดที่ใช้ไฟล์นั้นและฉันต้องการเปิดสำเนาแบบอ่านอย่างเดียวหรือไม่? เมื่อฉันตอบว่าใช่ Word GUI ก็โผล่ขึ้นมาจากที่ไหนเลยและเริ่มประมวลผลไฟล์ ฉันสงสัยว่าทำไมมันถึงเกิดขึ้น


3
เหตุใดจึงถูกแท็กเป็น win32 - ระบบข้อความอยู่ใน Windows V1 (ซึ่งเท่าที่ฉันจำได้คือ 8 บิต)
โฮแกน

คำตอบ:


187

ข้อความวนซ้ำเป็นโค้ดส่วนเล็ก ๆ ที่มีอยู่ในโปรแกรม Windows ดั้งเดิม มีลักษณะประมาณนี้:

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

GetMessage () Win32 API ดึงข้อความจาก Windows โดยทั่วไปโปรแกรมของคุณจะใช้เวลา 99.9% อยู่ที่นั่นเพื่อรอให้ Windows แจ้งว่ามีสิ่งที่น่าสนใจเกิดขึ้น TranslateMessage () เป็นฟังก์ชันตัวช่วยที่แปลข้อความบนแป้นพิมพ์ DispatchMessage () ทำให้แน่ใจว่าขั้นตอนหน้าต่างถูกเรียกด้วยข้อความ

ทุกโปรแกรม. NET ที่เปิดใช้งาน GUI จะมีลูปข้อความซึ่งเริ่มต้นโดย Application.Run ()

ความเกี่ยวข้องของการวนรอบข้อความกับ Office เกี่ยวข้องกับ COM โปรแกรม Office เป็นโปรแกรมที่เปิดใช้งาน COM ซึ่งเป็นวิธีการทำงานของคลาส Microsoft.Office.Interop COM ดูแลเธรดในนามของ COM coclass ทำให้มั่นใจได้ว่าการโทรที่ทำบนอินเทอร์เฟซ COM จะทำจากเธรดที่ถูกต้องเสมอ คลาส COM ส่วนใหญ่มีคีย์รีจิสทรีในรีจิสทรีที่ประกาศ ThreadingModel ของตนโดยคลาสทั่วไปส่วนใหญ่ (รวมถึง Office) ใช้ "Apartment" ซึ่งหมายความว่าวิธีเดียวที่ปลอดภัยในการเรียกใช้เมธอดอินเตอร์เฟสคือการโทรจากเธรดเดียวกับที่สร้างคลาสอ็อบเจ็กต์ หรือกล่าวอีกนัยหนึ่ง: โดยคลาส COM ส่วนใหญ่ไม่ปลอดภัยต่อเธรด

ทุกเธรดที่เปิดใช้งาน COM เป็นของอพาร์ตเมนต์ COM มีสองประเภทคือ Single Threaded Apartments (STA) และ Multi Thread Apartment (MTA) ต้องสร้างคลาส COM เธรดของอพาร์ตเมนต์บนเธรด STA คุณสามารถดูสิ่งนี้ได้ในโปรแกรม. NET จุดเริ่มต้นของเธรด UI ของ Windows Forms หรือโปรแกรม WPF มีแอตทริบิวต์ [STAThread] แบบจำลองอพาร์ทเมนต์สำหรับเธรดอื่น ๆ ถูกกำหนดโดยเมธอด Thread.SetApartmentState ()

ระบบประปา Windows ส่วนใหญ่จะทำงานไม่ถูกต้องหากเธรด UI ไม่ใช่ STA โดยเฉพาะอย่างยิ่ง Drag + Drop, คลิปบอร์ด, กล่องโต้ตอบของ Windows เช่น OpenFileDialog, การควบคุมเช่น WebBrowser, แอป UI Automation เช่นโปรแกรมอ่านหน้าจอ และเซิร์ฟเวอร์ COM จำนวนมากเช่น Office

ข้อกำหนดที่ยากสำหรับเธรด STA คือไม่ควรบล็อกและต้องปั๊มวนข้อความ การวนรอบข้อความมีความสำคัญเนื่องจากเป็นสิ่งที่ COM ใช้ในการจัดระเบียบวิธีการเชื่อมต่อจากเธรดหนึ่งไปยังอีกเธรดหนึ่ง แม้ว่า. NET จะทำให้การเรียกมาร์แชลเป็นเรื่องง่าย (เช่น ControlBeginInvoke หรือ Dispatcher BeginInvoke) แต่ก็เป็นเรื่องที่ยุ่งยากมากที่ต้องทำ เธรดที่ดำเนินการเรียกต้องอยู่ในสถานะที่รู้จักกันดี คุณไม่สามารถขัดจังหวะเธรดโดยพลการและบังคับให้เรียกใช้เมธอดได้ซึ่งจะทำให้เกิดปัญหาการกลับเข้ามาใหม่ที่น่ากลัว เธรดควร "ไม่ได้ใช้งาน" ไม่ยุ่งกับการเรียกใช้โค้ดใด ๆ ที่ทำให้สถานะของโปรแกรมกลายพันธุ์

บางทีคุณอาจเห็นว่านำไปสู่ที่ใด: ใช่เมื่อโปรแกรมกำลังดำเนินการวนรอบข้อความแสดงว่าไม่มีการใช้งาน การมาร์แชลจริงเกิดขึ้นผ่านหน้าต่างที่ซ่อนอยู่ซึ่ง COM สร้างขึ้นโดยใช้ PostMessage เพื่อให้มีขั้นตอนหน้าต่างของรหัสรันหน้าต่างนั้น บนเธรด STA วนข้อความช่วยให้มั่นใจว่ารหัสนี้ทำงาน


คำตอบที่ดีและละเอียดมาก เพียงเพื่อเพิ่ม - นอกจากนี้ยังมี STA พิเศษที่เรียกว่า STA หลักซึ่งเป็น STA แรกที่สร้างขึ้น ซึ่งควรเป็นสิ่งที่สร้างขึ้นโดยเธรด UI ของคุณ STA หลักคือที่ที่ส่วนประกอบที่มี threading model = none ถูกสร้างขึ้นหาก STA หลักของคุณไม่ใช่สิ่งที่สร้างโดยเธรด UI ของคุณคุณอาจพบปัญหาที่น่าสนใจเมื่อใช้ตัวควบคุม activex รุ่นเก่าที่ไม่มีโมเดลเธรด
quixver

12

"ปั๊มข้อความ" เป็นส่วนหลักของโปรแกรม Windows ใด ๆ ที่รับผิดชอบในการส่งข้อความหน้าต่างไปยังส่วนต่างๆของแอปพลิเคชัน นี่คือหัวใจหลักของการเขียนโปรแกรม Win32 UI เนื่องจากความแพร่หลายของแอปพลิเคชันจำนวนมากจึงใช้ปั๊มข้อความเพื่อส่งผ่านข้อความระหว่างโมดูลต่างๆซึ่งเป็นสาเหตุที่แอปพลิเคชัน Office จะหยุดทำงานหากทำงานโดยไม่มี UI

วิกิพีเดียมีคำอธิบายขั้นพื้นฐาน


ฉันเชื่อว่าเป็นไปไม่ได้ที่จะเขียนแอป windows โดยไม่มีข้อความวนซ้ำดังนั้นแอปพลิเคชันทั้งหมดจึงใช้ปั๊มข้อความ
Hogan

2
คุณยังสามารถเขียนแอป GUI ง่ายๆโดยไม่ต้องใช้แอปได้ตัวอย่างเช่นคุณสามารถเปิดกล่องข้อความโดยที่แอปของคุณเองไม่ต้องมีข้อความวนซ้ำในแอปของคุณ

หากคุณสร้างกล่องโต้ตอบผ่าน DialogBox หรือ DialogBox ทางอ้อม - คุณไม่จำเป็นต้องมีข้อความวนซ้ำคุณเพียงแค่ต้องจัดหาฟังก์ชัน (dlgproc) ที่จะเรียกโดย windows (และกล่องข้อความเป็นเพียงกล่องโต้ตอบธรรมดา ๆ )
quixver

6

John กำลังพูดถึงวิธีที่ระบบ Windows (และระบบที่ใช้หน้าต่างอื่น ๆ - X Window , Mac OS ดั้งเดิม .... ) ใช้อินเทอร์เฟซผู้ใช้แบบอะซิงโครนัสโดยใช้เหตุการณ์ผ่านระบบข้อความ

เบื้องหลังของแต่ละแอปพลิเคชันมีระบบการส่งข้อความที่แต่ละหน้าต่างสามารถส่งเหตุการณ์ไปยังหน้าต่างอื่น ๆ หรือผู้ฟังเหตุการณ์ซึ่งดำเนินการโดยการเพิ่มข้อความลงในคิวข้อความ มีลูปหลักที่มักจะเรียกดูคิวข้อความนี้จากนั้นส่งข้อความ (หรือเหตุการณ์) ไปยังผู้ฟัง

บทความ Wikipedia การวนซ้ำข้อความใน Microsoft Windowsแสดงโค้ดตัวอย่างของโปรแกรม Windows พื้นฐาน - และอย่างที่คุณเห็นในระดับพื้นฐานที่สุดโปรแกรม Windows เป็นเพียง "ปั๊มข้อความ"

ดังนั้นเพื่อดึงทั้งหมดเข้าด้วยกัน สาเหตุที่โปรแกรม windows ที่ออกแบบมาเพื่อรองรับ UI ไม่สามารถทำหน้าที่เป็นบริการได้เนื่องจากต้องมีการวนข้อความที่ทำงานตลอดเวลาเพื่อเปิดใช้งานการรองรับ UI หากคุณใช้เป็นบริการตามที่อธิบายไว้จะไม่สามารถประมวลผลการจัดการเหตุการณ์แบบอะซิงโครนัสภายในได้


6

ในCOMจะปั๊มข้อความให้เป็นอนุกรมและยกเลิกการเรียงลำดับข้อความที่ส่งระหว่างอพาร์ทเมนต์ อพาร์ทเมนต์เป็นกระบวนการขนาดเล็กที่สามารถเรียกใช้ส่วนประกอบ COM ได้ อพาร์ตเมนต์มีโหมดเธรดเดี่ยวและโหมดเธรดอิสระ อพาร์ทเมนต์แบบเธรดเดี่ยวส่วนใหญ่เป็นระบบดั้งเดิมสำหรับการใช้งานคอมโพเนนต์ COM ที่ไม่รองรับมัลติเธรด โดยทั่วไปจะใช้กับ Visual BASIC (เนื่องจากไม่รองรับโค้ดแบบมัลติเธรด) และแอปพลิเคชันเดิม

ฉันเดาว่าความต้องการปั๊มข้อความสำหรับWordเกิดจาก COM API หรือบางส่วนของแอปพลิเคชันที่ไม่ปลอดภัยสำหรับเธรด โปรดทราบว่าเธรดเธรด. NETและโมเดลการรวบรวมขยะไม่สามารถเล่นได้ดีกับ COM นอกกรอบ COM มีกลไกการรวบรวมขยะและแบบจำลองเธรดที่ง่ายมากซึ่งคุณต้องทำสิ่งต่างๆในแบบ COM การใช้Office PIAมาตรฐานยังคงทำให้คุณต้องปิดการอ้างอิงอ็อบเจ็กต์ COM อย่างชัดเจนดังนั้นคุณต้องติดตามทุกจุดจับ COM ที่สร้างขึ้น PIA จะสร้างสิ่งต่างๆอยู่เบื้องหลังหากคุณไม่ระวัง

การรวม. NET-COM เป็นหัวข้อทั้งหมดด้วยตัวเองและยังมีหนังสือที่เขียนเกี่ยวกับเรื่องนี้ด้วย แม้แต่การใช้ COM API สำหรับ Office จากแอปพลิเคชันเดสก์ท็อปแบบโต้ตอบคุณต้องข้ามผ่านห่วงและตรวจสอบให้แน่ใจว่ามีการเผยแพร่การอ้างอิงอย่างชัดเจน

Office สามารถสันนิษฐานได้ว่าไม่ปลอดภัยดังนั้นคุณจะต้องมีอินสแตนซ์ของ Word, ExcelหรือแอปพลิเคชันOfficeอื่น ๆแยกกันสำหรับแต่ละเธรด คุณจะต้องมีค่าใช้จ่ายในการเริ่มต้นหรือดูแลเธรดพูล เธรดพูลจะต้องได้รับการทดสอบอย่างพิถีพิถันเพื่อให้แน่ใจว่าการอ้างอิง COM ทั้งหมดถูกนำออกใช้อย่างถูกต้อง แม้แต่การเริ่มต้นและปิดอินสแตนซ์คุณต้องตรวจสอบให้แน่ใจว่าการอ้างอิงทั้งหมดได้รับการเผยแพร่อย่างถูกต้อง ความล้มเหลวในการจุด i ของคุณและข้าม t ของคุณที่นี่จะส่งผลให้วัตถุ COM ที่ตายแล้วจำนวนมากและแม้แต่อินสแตนซ์ของ Word ที่กำลังทำงานอยู่ทั้งหมดก็รั่ว


1
คำตอบของคุณมีความไม่ถูกต้องเล็กน้อย อพาร์ทเมนต์มี 3 ประเภท ได้แก่ STA (เธรดเดี่ยว), MTA (เธรดหลายเธรด) และ NTA (เธรดกลาง) เธรดฟรีใช้เพื่ออธิบายส่วนประกอบที่รวมมาร์แชลเลอร์เธรดอิสระไม่มีสิ่งที่เรียกว่าอพาร์ทเมนต์เธรดฟรี COM ใช้ข้อความเพื่อสื่อสารกับ STAs สำหรับคอมโพเนนต์ที่อยู่ใน MTA (หรือที่รวมมาร์แชลเลอร์เธรดอิสระ) ไม่จำเป็นต้องมีการวนซ้ำข้อความ AFAIK - lpc ใช้เพื่อจัดเรียงข้อมูลจากการเรียกเธรดไปยังเธรดจากพูลเธรด RPC ซึ่งจะเรียกใช้เมธอด
quixver


0

ฉันคิดว่าการสนทนาของช่อง 9นี้มีคำอธิบายที่กระชับดี:

กระบวนการสื่อสารหน้าต่างนี้เกิดขึ้นได้โดยสิ่งที่เรียกว่า Windows Message Pump คิดว่า Message Pump เป็นเอนทิตีที่ช่วยให้เกิดความร่วมมือระหว่างหน้าต่างแอปพลิเคชันและเดสก์ท็อป


2
ว้าว ... นั่นเป็นคำพูดที่น่ากลัวและทำให้เข้าใจผิด ("เอนทิตี" หรือไม่เอ่อ .. ไม่)
โฮแกน

4
เอนทิตี - วัตถุ: สิ่งที่มีอยู่เป็นหรือถูกมองว่าเป็นวัตถุแยกชิ้นเดียวencarta.msn.com/dictionary_1861608661/entity.html
Matthew Whited
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.