2008-10-03 40 views
97

Từ bài viết MSDN trên STAThread:STAThread và đa luồng

Chỉ ra rằng mô hình luồng COM cho một ứng dụng là đơn luồng căn hộ (STA).

(Để tham khảo, đó là the entire article.)

Single-ren căn hộ ... OK, đó đã đi qua đầu tôi. Ngoài ra, tôi đọc ở đâu đó trừ khi ứng dụng của bạn sử dụng COM interop, thuộc tính này thực sự không làm gì cả. Vậy chính xác nó sẽ làm gì và nó ảnh hưởng như thế nào đến các ứng dụng đa luồng? Nên các ứng dụng đa luồng (bao gồm bất kỳ thứ gì từ bất kỳ ai sử dụng Timer s đến các cuộc gọi phương thức không đồng bộ, không chỉ các luồng và các loại tương tự) sử dụng MTAThread, ngay cả khi nó 'vừa an toàn'? STAThread và MTAThread thực sự làm gì?

Trả lời

58

Luồng căn hộ là khái niệm COM; nếu bạn không sử dụng COM và không có API nào mà bạn gọi sử dụng COM "dưới bìa", thì bạn không cần phải lo lắng về căn hộ.

Nếu bạn cần lưu ý về căn hộ thì chi tiết có thể nhận được a little complicated; một phiên bản có thể quá minh họa là các đối tượng COM được gắn nhãn là STA phải được chạy trên một STAThread và các đối tượng COM được đánh dấu MTA phải được chạy trên một chuỗi MTA. Sử dụng các quy tắc này, COM có thể tối ưu hóa các cuộc gọi giữa các đối tượng khác nhau này, tránh marshaling khi không cần thiết.

+7

Điều đó là đơn giản. Các đối tượng đa luồng có thể chạy trong bất kỳ chuỗi nào. Một đối tượng có thể chỉ chạy trong căn hộ mà chúng được tạo ra. –

+27

Một cuộc gọi từ một đối tượng STA trên một chuỗi STA, đến một đối tượng MTA, sẽ sắp xếp lại thành một chuỗi MTA (trừ khi đối tượng MTA thực hiện trình gỡ rối chuỗi miễn phí) . Như tôi đã nói, các chi tiết có thể trở nên phức tạp. (Tôi đã làm việc trên nhóm COM trong một số năm * cười *) – Bruce

+9

Đôi khi bạn cần phải nhận thức được điều này ngay cả khi bạn không sử dụng COM trực tiếp. Chủ đề phải sử dụng mô hình Căn hộ đơn luồng nếu nó hiển thị bất kỳ cửa sổ đồ họa nào. Đây là lý do tại sao [STAThread] luôn hiển thị ở trên cùng của phương thức chính trong một ứng dụng biểu mẫu windows. –

3

Điều gì làm nó đảm bảo rằng CoInitialize được gọi là chỉ định COINIT_APARTMENTTHREADED làm thông số. Nếu bạn không sử dụng bất kỳ thành phần COM hoặc điều khiển ActiveX nó sẽ không có hiệu lực trên bạn cả. Nếu bạn làm như vậy thì nó rất quan trọng.

Controls có ren căn hộ là một cách hiệu quả đơn ren, các cuộc gọi được thực hiện đối với họ chỉ có thể được xử lý trong căn hộ mà họ đã tạo ra trong

Một số chi tiết hơn từ MSDN:.

Đối tượng được tạo ra trong một căn hộ đơn luồng (STA) nhận các cuộc gọi chỉ chỉ từ chủ đề của căn hộ, do đó, cuộc gọi được sắp xếp theo thứ tự và chỉ đến tại ranh giới hàng đợi tin nhắn (khi chức năng Win32 PeekMessage hoặc SendMessage được gọi).

Đối tượng được tạo trên chuỗi COM trong một số căn hộ đa luồng (MTA) phải là có thể nhận cuộc gọi phương thức từ các chủ đề khác bất kỳ lúc nào. Bạn sẽ thường thực hiện một số hình thức kiểm soát đồng thời trong mã một multithreaded đối tượng bằng cách sử dụng Win32 đồng bộ hóa nguyên thủy như quan trọng phần, Cột, hoặc mutexes để giúp bảo vệ dữ liệu của đối tượng.

Khi một đối tượng mà được cấu hình để chạy trong căn hộ ren trung lập (NTA) được gọi bởi một sợi là trong hoặc một STA hoặc MTA, mà thread chuyển đến NTA. Nếu chủ đề này sau đó gọi CoInitializeEx, cuộc gọi không thành công và trả lại RPC_E_CHANGED_MODE.

+0

Bài viết MSDN hữu ích từ phối cảnh COM nhưng bạn có thể cho tôi biết khi nào các cuộc gọi .NET 'CoInitialize()' trả lời thuộc tính 'STAThread' /' ApartmentState'? Lưu ý: Bài viết trên MSDN có tại đây: [Hàm CoInitializeEx] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms695279%28v=vs.85%29.aspx). – jrh

+0

@jrh nó gọi nó khi thread được bắt đầu –

+0

Có [thread-> SetApartment] (https://github.com/dotnet/coreclr/blob/master/src/vm/comsynchronizable.cpp#L987) sử dụng 'CoInitialize () 'nội bộ? Tôi đã truy tìm thuộc tính STAThread ở dưới đó nhưng đường mòn đã biến mất (tôi không tìm được nguồn cho 'Thread :: SetApartment'). Là lớp Thread từ thread.h (COM thread.h) được ghi lại ở bất cứ đâu? Là nó MFC, ATL, hoặc cái gì khác? – jrh

-14

STAThread được viết trước chức năng chính của dự án C# GUI. Nó không làm gì ngoài việc cho phép chương trình tạo một luồng đơn.