STAThread และมัลติเธรด


102

จากบทความ MSDN ใน STAThread:

ระบุว่าแบบจำลองเธรด COM สำหรับแอ็พพลิเคชันเป็น single-threaded apartment (STA)

(สำหรับการอ้างอิงนั่นคือบทความทั้งหมด )

อพาร์ทเมนต์แบบเธรดเดี่ยว ... ตกลงที่อยู่เหนือหัวของฉัน นอกจากนี้ฉันอ่านที่ไหนสักแห่งเว้นแต่แอปพลิเคชันของคุณจะใช้ COM interop แอตทริบิวต์นี้ไม่ได้ทำอะไรเลย มันทำอะไรกันแน่และมีผลต่อแอพพลิเคชั่นมัลติเธรดอย่างไร? แอพพลิเคชั่นแบบมัลติเธรด (ซึ่งรวมถึงอะไรก็ตามจากใครก็ตามที่ใช้Timers ไปจนถึงการเรียกเมธอดอะซิงโครนัสไม่ใช่แค่เธรดพูลและสิ่งที่คล้ายกัน) ใช้ MTAThread แม้ว่ามันจะ 'เพียงเพื่อความปลอดภัย' ก็ตาม STAThread และ MTAThread ทำอะไรได้จริง?

คำตอบ:


60

เธรดอพาร์ตเมนต์เป็นแนวคิด COM หากคุณไม่ได้ใช้ COM และไม่มี API ใดที่คุณเรียกว่าใช้ COM "ภายใต้ฝาครอบ" คุณก็ไม่ต้องกังวลเกี่ยวกับอพาร์ตเมนต์

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


7
นั่นคือตัวย่อ อ็อบเจ็กต์มัลติเธรดสามารถรันในเธรดใดก็ได้ อพาร์ทเมนต์เธรดอ็อบเจ็กต์สามารถทำงานได้เฉพาะในอพาร์ทเมนต์ที่สร้างขึ้นเท่านั้น
1800 ข้อมูล

28
การเรียกจากอ็อบเจ็กต์ STA บนเธรด STA ไปยังอ็อบเจ็กต์ MTA จะย้ายไปยังเธรด MTA (เว้นแต่อ็อบเจ็กต์ MTA จะใช้มาร์แชลเลอร์ฟรีเธรด) อย่างที่ฉันพูดรายละเอียดอาจซับซ้อน (ผมทำงานในทีม COM สำหรับจำนวนของปียิ้ม )
บรูซ

9
บางครั้งคุณต้องระวังเรื่องนี้แม้ว่าคุณจะไม่ได้ใช้ COM โดยตรงก็ตาม เธรดต้องใช้โมเดล Single-Threaded Apartment หากแสดงหน้าต่างกราฟิกใด ๆ นี่คือเหตุผลว่าทำไม [STAThread] จึงแสดงอยู่ด้านบนของวิธีการหลักในแอปพลิเคชันฟอร์ม windows
Justin Ethier

6
ไม่สามารถใช้กล่องโต้ตอบแบบอักษรหรือไฟล์ได้โดยที่คุณไม่รู้? ฉันจะถือว่าพวกเขาทำภายในนั่นไม่ได้หมายความว่าแอปพลิเคชัน Windows Forms เกือบทั้งหมดจะต้องมีการตั้งค่า STAThread หรือไม่? ยกโทษให้กับสมมติฐานที่ไร้เดียงสาของฉันเนื่องจากฉันไม่ได้เขียนโปรแกรม COM
Brett Ryan

4
คำตอบโดยละเอียดสำหรับผู้ที่สนใจ: stackoverflow.com/questions/4154429/apartmentstate-for-dummies
jgauffin

3

สิ่งที่ทำให้มั่นใจได้ว่าCoInitializeเรียกว่าการระบุ COINIT_APARTMENTTHREADED เป็นพารามิเตอร์ หากคุณไม่ได้ใช้คอมโพเนนต์ COM หรือตัวควบคุม ActiveX ใด ๆ จะไม่มีผลกับคุณเลย ถ้าคุณทำมันก็สำคัญมาก

การควบคุมที่เป็นเธรดอพาร์ทเมนต์เป็นเธรดเดียวอย่างมีประสิทธิภาพการโทรไปยังพวกเขาสามารถดำเนินการได้ในอพาร์ตเมนต์ที่สร้างขึ้นเท่านั้น

รายละเอียดเพิ่มเติมจาก MSDN:

ออบเจ็กต์ที่สร้างในอพาร์ทเมนต์แบบเธรดเดียว (STA) จะรับเมธอดการเรียกจากเธรดของอพาร์ตเมนต์เท่านั้นดังนั้นการโทรจึงเป็นแบบอนุกรมและมาถึงขอบเขตของคิวข้อความเท่านั้น (เมื่อฟังก์ชัน Win32 PeekMessage หรือ SendMessage ถูกเรียก)

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

เมื่ออ็อบเจ็กต์ที่กำหนดค่าให้รันในอพาร์ทเมนต์เธรดที่เป็นกลาง (NTA) ถูกเรียกโดยเธรดที่อยู่ใน STA หรือ MTA เธรดนั้นจะโอนไปยัง NTA หากเธรดนี้เรียกใช้ CoInitializeEx ในภายหลังการเรียกจะล้มเหลวและส่งคืน RPC_E_CHANGED_MODE


บทความ MSDN มีประโยชน์จากมุมมอง COM แต่คุณสามารถบอกฉันได้ไหมว่าเมื่อใดที่. NET เรียกCoInitialize()เพื่อตอบสนองต่อSTAThreadแอตทริบิวต์ / ApartmentState? หมายเหตุ: บทความใน MSDN อยู่ที่นี่: ฟังก์ชั่น CoInitializeEx
jrh

ไม่thread-> SetApartmentใช้CoInitialize()ภายใน? ฉันติดตามแอตทริบิวต์ STAThread จนสุด แต่เส้นทางกลับเย็นลง (ฉันหาแหล่งที่มาไม่ได้Thread::SetApartment) คลาส Thread จาก thread.h (COM thread.h) ถูกบันทึกไว้ที่ใดหรือไม่ เป็น MFC, ATL หรืออย่างอื่น?

@jrh ฉันไม่ทราบรายละเอียดมากกว่านั้นขออภัย
1800 ข้อมูล

-15

STAThread เขียนก่อนฟังก์ชันหลักของโครงการ C # GUI มันไม่ทำอะไรเลยนอกจากอนุญาตให้โปรแกรมสร้างเธรดเดียว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.