คุณสามารถอธิบาย STA และ MTA ได้ไหม


391

คุณช่วยอธิบาย STA และ MTA ด้วยคำพูดของคุณเองได้ไหม?

นอกจากนี้สิ่งที่เป็นหัวข้อพาร์ทเมนต์และพวกเขาเกี่ยวข้องกับ COM เท่านั้น? ถ้าเป็นเช่นนั้นทำไม


1
ดูเพิ่มเติม: การทำความเข้าใจ COM พาร์ทเมนท์ส่วนที่ 1 , ส่วนที่ 2
jrh

คำตอบ:


361

รูปแบบการเธรด COM เรียกว่าแบบจำลอง "อพาร์ทเมนท์" ซึ่งบริบทการดำเนินการของวัตถุ COM ที่เริ่มต้นถูกเชื่อมโยงกับเธรดเดี่ยว (Single Thread Apartment) หรือเธรดจำนวนมาก (Multi Thread Apartment) ในรุ่นนี้วัตถุ COM ที่เริ่มต้นครั้งแรกในอพาร์ทเมนต์เป็นส่วนหนึ่งของอพาร์ทเมนต์นั้นในช่วงระยะเวลาของการใช้งานจริง

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

ถ้าวัตถุ COM สามารถจัดการกับการซิงโครไนซ์ของตัวเองแล้วรุ่น MTA สามารถใช้ที่อนุญาตให้มีหลายเธรดเพื่อโต้ตอบกับวัตถุโดยไม่เรียก marshalled


1
ดีอ่านรายละเอียดเพิ่มเติม: รายละเอียด: คำอธิบายและการทำงานของ OLE Threading รุ่น
noseratio

208

ทุกอย่างลงไปถึงวิธีการจัดการการโทรไปยังวัตถุและการป้องกันที่จำเป็น วัตถุ COM สามารถถามรันไทม์เพื่อป้องกันไม่ให้ถูกเรียกโดยหลายเธรดในเวลาเดียวกัน สิ่งที่ไม่สามารถเรียกได้พร้อมกันจากเธรดที่แตกต่างกันดังนั้นพวกเขาจึงต้องปกป้องข้อมูลของตัวเอง

นอกจากนี้ยังจำเป็นสำหรับรันไทม์เพื่อป้องกันการโทรวัตถุ COM ไม่ให้บล็อกส่วนต่อประสานผู้ใช้หากมีการโทรจากเธรดส่วนต่อประสานผู้ใช้

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

เธรดสามารถอยู่ในอพาร์ทเมนต์แบบเธรดเดียว (ซึ่งในกรณีนี้เป็นเธรดเดียวในอพาร์ทเมนต์นั้น) หรือในอพาร์ตเมนต์แบบมัลติเธรด พวกเขาระบุว่าเมื่อใดที่เธรดเริ่มต้น COM สำหรับเธรดนั้น

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

ในทางตรงกันข้ามเธรด MTA ทั้งหมดแบ่งปัน MTA เดียวสำหรับกระบวนการ COM อาจเริ่มเธรดของผู้ปฏิบัติงานใหม่เพื่อจัดการการโทรเข้าหากไม่มีเธรดพร้อมใช้งานจนถึงขีด จำกัด ของพูล หัวข้อการโทรออกเพียงแค่บล็อก

เพื่อความง่ายเราจะพิจารณาเฉพาะอ็อบเจกต์ที่นำไปใช้ใน DLLs ซึ่งโฆษณาในรีจิสตรีที่สนับสนุนด้วยการตั้งThreadingModelค่าสำหรับคีย์ของคลาส มีสี่ตัวเลือก:

  • เธรดหลัก ( ThreadingModelไม่มีค่า) วัตถุถูกสร้างขึ้นบนเธรด UI หลักของโฮสต์และการโทรทั้งหมดจะถูกจัดเรียงในเธรดนั้น โรงงานคลาสจะถูกเรียกบนเธรดนั้นเท่านั้น
  • Apartment. สิ่งนี้บ่งชี้ว่าคลาสสามารถรันบนเธรดโหมดเธรดเดี่ยวใด ๆ หากเธรดที่สร้างขึ้นเป็นเธรด STA วัตถุจะทำงานบนเธรดนั้นมิฉะนั้นจะถูกสร้างขึ้นใน STA หลัก - หากไม่มี STA หลักอยู่เธรด STA จะถูกสร้างขึ้น (ซึ่งหมายความว่าเธรด MTA ที่สร้างอพาร์ทเมนต์วัตถุจะเป็น marshalling การเรียกทั้งหมดไปยังเธรดอื่น) โรงงานคลาสสามารถถูกเรียกพร้อมกันโดยเธรด STA หลายเธรดดังนั้นจึงต้องป้องกันข้อมูลภายในจากสิ่งนี้
  • Free. สิ่งนี้บ่งชี้คลาสที่ออกแบบมาให้ทำงานใน MTA มันจะโหลดใน MTA เสมอแม้ว่าจะสร้างโดยเธรด STA ซึ่งหมายความว่าการเรียกเธรด STA จะถูกจัดเรียงใหม่อีกครั้ง นี่เป็นเพราะFreeวัตถุถูกเขียนโดยทั่วไปด้วยความคาดหวังว่ามันสามารถปิดกั้น
  • Both. คลาสเหล่านี้มีความยืดหยุ่นและโหลดในอพาร์ตเมนต์ที่สร้างขึ้น พวกเขาจะต้องเขียนให้เหมาะสมกับข้อกำหนดทั้งสองชุดอย่างไรก็ตาม: พวกเขาจะต้องปกป้องสถานะภายในของพวกเขาจากการโทรพร้อมกันในกรณีที่พวกเขากำลังโหลดใน MTA แต่ต้องไม่บล็อกในกรณีที่พวกเขาโหลดใน STA

จาก. NET Framework โดยทั่วไปแล้วใช้[STAThread]กับเธรดใดก็ได้ที่สร้าง UI เธรดผู้ปฏิบัติงานควรใช้ MTA เว้นแต่ว่าพวกเขากำลังจะใช้Apartmentคอมโพเนนต์ COM ที่มีเครื่องหมายซึ่งในกรณีนี้ใช้ STA เพื่อหลีกเลี่ยงปัญหาค่าใช้จ่ายในการจัดเรียงและการขยายขีดความสามารถหากองค์ประกอบเดียวกันถูกเรียกจากหลายเธรด (เนื่องจากแต่ละเธรด ส่วนประกอบในการเปิด) มันง่ายกว่าถ้าคุณใช้วัตถุ COM แยกกันต่อเธรดไม่ว่าองค์ประกอบนั้นจะอยู่ใน STA หรือ MTA


ฉันชอบข้อสรุปสุดท้ายของคุณ แต่เกี่ยวกับสิ่งนั้นฉันควรทำอย่างไรหากฉันต้องการให้ UI ของฉันเพิ่ม UserControl ว่าสิ่งเดียวที่ทำคือการสร้าง gif (เช่นตัวโหลด) ... ฉันกำลังมีปัญหากับสิ่งนี้ gif ไม่หมุนถ้าพวกเขาอยู่ในเธรดเดียวกัน ... และฉันไม่แน่ใจว่า MTA บน UI เป็นความคิดที่ดีคุณจะทำอย่างไร
Yogurtu

2
@Yogurtu: ทำไมคุณกังวลเกี่ยวกับรูปแบบการทำเกลียว COM เลย? การตัดสินใจ STA / MTA เกี่ยวข้องเฉพาะเมื่อคุณใช้วัตถุ COM ในรหัสของคุณ คุณไม่สามารถใช้ MTA สำหรับ UI - internals ของ. NET ไม่ได้มีวัตถุประสงค์เพื่อใช้ในวิธีนั้น หากแอนิเมชันของคุณหยุดอยู่นั่นเป็นเพราะคุณหยุดปั๊มข้อความบนเธรด UI ของคุณ ย้ายการทำงานที่ใช้เวลานานไปยัง BackgroundWorker หรือแยกเป็นขั้นตอนเล็ก ๆ งานต้องใช้เวลา <16ms เพื่อให้ภาพเคลื่อนไหวราบรื่น 60Hz!
Mike Dimmick

"อพาร์ตเมนต์" และ appdomain ต่างกันอย่างไร
Puchacz

78

ฉันพบว่าคำอธิบายที่มีอยู่ gobbledygook เกินไป นี่คือคำอธิบายของฉันในภาษาอังกฤษธรรมดา:

STA: ถ้าเธรดสร้างวัตถุ COM ที่ตั้งค่าเป็น STA (เมื่อเรียก CoCreateXXX คุณสามารถส่งค่าสถานะที่ตั้งค่าวัตถุ COM เป็นโหมด STA) เฉพาะเธรดนี้เท่านั้นที่สามารถเข้าถึงวัตถุ COM นี้ได้ (นั่นคือความหมายของ STA ) เธรดอื่นที่พยายามเรียกใช้เมธอดบนวัตถุ COM นี้อยู่ภายใต้ประทุนกลายเป็นส่งข้อความไปยังเธรดที่สร้าง (เป็นเจ้าของ) วัตถุ COM อย่างเงียบ ๆ นี่เป็นความจริงที่ว่าเฉพาะเธรดที่สร้างตัวควบคุม UI เท่านั้นที่สามารถเข้าถึงได้โดยตรง และกลไกนี้มีไว้เพื่อป้องกันการล็อค / ปลดล็อคที่ซับซ้อน

MTA: ถ้าเธรดสร้างวัตถุ COM ที่ตั้งค่าเป็น MTA แล้วทุก ๆ เธรดสามารถเรียกเมธอดได้โดยตรง

นั่นเป็นส่วนสำคัญของมัน แม้ว่าในทางเทคนิคจะมีรายละเอียดบางอย่างที่ฉันไม่ได้พูดถึงเช่นในย่อหน้า 'STA' แต่ตัวสร้างเธรดต้องเป็น STA แต่นี่คือสิ่งที่คุณต้องรู้เพื่อทำความเข้าใจ STA / MTA / NA


23

STA (Single Threaded Apartment) นั้นเป็นแนวคิดที่ว่ามีเพียงหนึ่งเธรดที่จะโต้ตอบกับโค้ดของคุณในแต่ละครั้ง การโทรเข้าอพาร์ทเมนต์ของคุณจะถูกจัดการผ่านทางข้อความ windows (โดยใช้หน้าต่างที่มองไม่เห็น) สิ่งนี้อนุญาตให้การโทรถูกจัดคิวและรอการดำเนินการให้เสร็จสมบูรณ์

MTA (Multi Threaded Apartment) เป็นที่ที่หลาย ๆ เธรดสามารถทำงานได้ในเวลาเดียวกันและความรับผิดชอบของคุณในฐานะผู้พัฒนาเพื่อจัดการกับความปลอดภัยของเธรด

มีมากขึ้นที่จะเรียนรู้เกี่ยวกับการทำเกลียวใน COM แต่ถ้าคุณมีปัญหาในการทำความเข้าใจสิ่งที่พวกเขาเป็นแล้วฉันจะบอกว่าการทำความเข้าใจว่า STA คืออะไรและมันทำงานอย่างไรจะเป็นจุดเริ่มต้นที่ดีที่สุดเพราะวัตถุ COM ส่วนใหญ่เป็น STA

Apartment Threads หากเธรดอยู่ในอพาร์ทเมนต์เดียวกันกับออบเจ็กต์ที่ใช้อพาร์ทเมนต์จะเป็นเธรดของอพาร์ทเมนต์ ฉันคิดว่านี่เป็นเพียงแนวคิด COM เพราะเป็นเพียงวิธีการพูดคุยเกี่ยวกับวัตถุและเธรดที่พวกเขาโต้ตอบกับ ...


19

แต่ละ EXE ที่โฮสต์ตัวควบคุม COM หรือ OLE กำหนดสถานะของอพาร์ทเมนท์ สถานะพาร์ทเมนต์เป็นค่าเริ่มต้น STA (และสำหรับโปรแกรมส่วนใหญ่ควรเป็น STA)

STA - ตัวควบคุม OLE ทั้งหมดตามความจำเป็นต้องอยู่ใน STA STA หมายความว่าวัตถุ COM ของคุณต้องถูกจัดการบนเธรด UI และไม่สามารถส่งผ่านไปยังเธรดอื่น ๆ ได้ (เหมือนกับองค์ประกอบ UI ใด ๆ ใน MFC) อย่างไรก็ตามโปรแกรมของคุณยังสามารถมีหลายเธรด

MTA - คุณสามารถจัดการวัตถุ COM บนเธรดใด ๆ ในโปรแกรมของคุณ


13
"STA หมายความว่า COM-object ของคุณต้องถูกจัดการบนเธรด UI เสมอ" ฉันไม่คิดว่ามันถูกต้องจริง ๆ ... มันไม่จำเป็นต้องอยู่ในเธรด "UI" เพียงอย่างเดียวเธรด STA ที่มี ปั๊มข้อความเพราะมันเรียกการทำข้อมูลให้ตรงกันโดยใช้ข้อความ เธรด UI มักจะตรงตามข้อกำหนดเหล่านี้ แต่ไม่ใช่ความเป็นไปได้เท่านั้น
Brian ONeil

12

ตามความเข้าใจของฉัน 'อพาร์ทเมนท์' ถูกใช้เพื่อปกป้องวัตถุ COM จากปัญหาหลายเธรด

ถ้าวัตถุ COM ไม่ปลอดภัยเธรดควรประกาศเป็นวัตถุ STA จากนั้นเฉพาะเธรดที่สร้างขึ้นเท่านั้นที่สามารถเข้าถึงได้ เธรดการสร้างควรประกาศว่าตนเองเป็นเธรด STA ภายใต้ประทุนเธรดจะเก็บข้อมูล STA ไว้ใน TLS (Thread Local Storage) เราเรียกพฤติกรรมนี้ว่าเธรดเข้าสู่อพาร์ทเมนต์ STA เมื่อเธรดอื่นต้องการเข้าถึงวัตถุ COM นี้ควรจัดการการเข้าถึงเธรดการสร้าง โดยทั่วไปเธรดการสร้างใช้กลไกข้อความเพื่อประมวลผลการโทรที่ถูกผูกไว้

ถ้าวัตถุ COM เป็นเธรดที่ปลอดภัยมันควรประกาศเป็นวัตถุ MTA วัตถุ MTA สามารถเข้าถึงได้โดยหลายกระทู้


4

รหัสที่เรียก COM วัตถุ DLLs (ตัวอย่างเช่นการอ่านไฟล์ข้อมูลที่เป็นกรรมสิทธิ์) อาจทำงานได้ดีในส่วนติดต่อผู้ใช้ แต่แขวนอย่างลึกลับจากบริการ เหตุผลก็คือส่วนติดต่อผู้ใช้. Net 2.0 จะถือว่า STA (thread-safe) ในขณะที่บริการถือว่า MTA ((ก่อนหน้านั้นจะถือว่าบริการ STA) การสร้างเธรด STA สำหรับการโทร COM ทุกครั้งในบริการสามารถเพิ่มค่าใช้จ่ายได้อย่างมาก

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