Câu trả lời:
Mô hình luồng COM được gọi là mô hình "căn hộ", trong đó bối cảnh thực hiện của các đối tượng COM được khởi tạo được liên kết với một luồng đơn (Căn hộ một luồng) hoặc nhiều luồng (Căn hộ đa luồng). Trong mô hình này, một đối tượng COM, một khi được khởi tạo trong một căn hộ, là một phần của căn hộ đó trong suốt thời gian chạy.
Mô hình STA được sử dụng cho các đối tượng COM không phải là luồng an toàn. Điều đó có nghĩa là họ không xử lý đồng bộ hóa của riêng họ. Một sử dụng phổ biến của điều này là một thành phần UI. Vì vậy, nếu một luồng khác cần tương tác với đối tượng (chẳng hạn như nhấn nút trong một biểu mẫu) thì thông báo sẽ được sắp xếp theo luồng STA. Các cửa sổ hình thành hệ thống bơm tin nhắn là một ví dụ về điều này.
Nếu đối tượng COM có thể xử lý đồng bộ hóa của riêng nó thì mô hình MTA có thể được sử dụng trong đó nhiều luồng được phép tương tác với đối tượng mà không cần các cuộc gọi được sắp xếp theo thứ tự.
Tất cả đều thuộc về cách các cuộc gọi đến các đối tượng được xử lý và mức độ bảo vệ mà chúng cần. Các đối tượng COM có thể yêu cầu bộ thực thi bảo vệ chúng khỏi bị gọi bởi nhiều luồng cùng lúc; những cái không có khả năng có thể được gọi đồng thời từ các luồng khác nhau, vì vậy chúng phải bảo vệ dữ liệu của riêng chúng.
Ngoài ra, thời gian chạy cũng cần thiết để ngăn cuộc gọi đối tượng COM chặn giao diện người dùng, nếu cuộc gọi được thực hiện từ luồng giao diện người dùng.
Một căn hộ là nơi để các đối tượng sống và chúng chứa một hoặc nhiều luồng. Căn hộ xác định những gì xảy ra khi các cuộc gọi được thực hiện. Các cuộc gọi đến các đối tượng trong một căn hộ sẽ được nhận và xử lý trên bất kỳ chuỗi nào trong căn hộ đó, ngoại trừ một cuộc gọi bởi một luồng đã có trong căn hộ bên phải được xử lý bởi chính nó (tức là một cuộc gọi trực tiếp đến đối tượng).
Chủ đề có thể ở trong Căn hộ một luồng (trong trường hợp đó là chủ đề duy nhất trong căn hộ đó) hoặc trong Căn hộ đa luồng. Chúng chỉ định cái nào khi luồng khởi tạo COM cho luồng đó.
STA chủ yếu để tương thích với giao diện người dùng, được gắn với một luồng cụ thể. STA nhận thông báo về các cuộc gọi để xử lý bằng cách nhận thông báo cửa sổ đến một cửa sổ ẩn; khi thực hiện cuộc gọi đi, nó sẽ bắt đầu một vòng lặp thông báo phương thức để ngăn các tin nhắn cửa sổ khác được xử lý. Bạn có thể chỉ định bộ lọc thư sẽ được gọi để ứng dụng của bạn có thể trả lời các tin nhắn khác.
Ngược lại, tất cả các luồng MTA chia sẻ một MTA duy nhất cho quá trình. COM có thể bắt đầu một luồng công nhân mới để xử lý một cuộc gọi đến nếu không có luồng nào, đến giới hạn nhóm. Chủ đề thực hiện cuộc gọi đi chỉ đơn giản là chặn.
Để đơn giản, chúng tôi sẽ chỉ xem xét các đối tượng được triển khai trong DLL, quảng cáo trong sổ đăng ký những gì chúng hỗ trợ, bằng cách đặt ThreadingModel
giá trị cho khóa của lớp. Có bốn lựa chọn:
ThreadingModel
giá trị không có mặt). Đối tượng được tạo trên luồng UI chính của máy chủ và tất cả các cuộc gọi được sắp xếp theo luồng đó. Các nhà máy lớp sẽ chỉ được gọi trên chủ đề đó.Apartment
. Điều này chỉ ra rằng lớp có thể chạy trên bất kỳ luồng chế độ đơn luồng nào. Nếu luồng tạo ra nó là một luồng STA, đối tượng sẽ chạy trên luồng đó, nếu không nó sẽ được tạo trong STA chính - nếu không có STA chính tồn tại, một luồng STA sẽ được tạo cho nó. (Điều này có nghĩa là các luồng MTA tạo các đối tượng Căn hộ sẽ sắp xếp tất cả các cuộc gọi đến một luồng khác.) Nhà máy lớp có thể được gọi đồng thời bởi nhiều luồng STA để nó phải bảo vệ dữ liệu bên trong của nó chống lại điều này.Free
. Điều này chỉ ra một lớp được thiết kế để chạy trong MTA. Nó sẽ luôn tải trong MTA, ngay cả khi được tạo bởi một luồng STA, điều đó một lần nữa có nghĩa là các lệnh gọi của luồng STA sẽ được sắp xếp lại. Điều này là do một Free
đối tượng thường được viết với kỳ vọng rằng nó có thể chặn.Both
. Các lớp này linh hoạt và tải trong bất kỳ căn hộ nào chúng được tạo ra. Tuy nhiên, chúng phải được viết để phù hợp với cả hai bộ yêu cầu: chúng phải bảo vệ trạng thái bên trong của chúng trước các cuộc gọi đồng thời, trong trường hợp chúng được tải trong MTA, nhưng không được chặn, trong trường hợp chúng được tải trong STA.Từ .NET Framework, về cơ bản chỉ cần sử dụng [STAThread]
trên bất kỳ luồng nào tạo UI. Các luồng công nhân nên sử dụng MTA, trừ khi họ sẽ sử dụng Apartment
các thành phần COM được đánh dấu, trong trường hợp đó sử dụng STA để tránh các vấn đề về khả năng mở rộng và khả năng mở rộng nếu cùng một thành phần được gọi từ nhiều luồng (vì mỗi luồng sẽ phải chờ các thành phần lần lượt). Mọi thứ xung quanh sẽ dễ dàng hơn nhiều nếu bạn sử dụng một đối tượng COM riêng cho mỗi luồng, cho dù thành phần đó nằm trong STA hay MTA.
Tôi thấy những lời giải thích hiện có quá gobbledygook. Đây là lời giải thích của tôi bằng tiếng Anh đơn giản:
STA: Nếu một luồng tạo một đối tượng COM được đặt thành STA (khi gọi CoCreateXXX, bạn có thể chuyển một cờ đặt đối tượng COM sang chế độ STA), thì chỉ chủ đề này mới có thể truy cập đối tượng COM này (nghĩa là STA ), các luồng khác đang cố gắng gọi các phương thức trên đối tượng COM này nằm dưới mui xe âm thầm chuyển thành gửi tin nhắn đến luồng tạo (sở hữu) đối tượng COM. Điều này rất giống với thực tế là chỉ có luồng tạo ra điều khiển UI mới có thể truy cập trực tiếp. Và cơ chế này có nghĩa là để ngăn chặn các hoạt động khóa / mở khóa phức tạp.
MTA: Nếu một luồng tạo một đối tượng COM được đặt thành MTA, thì hầu như mọi luồng đều có thể gọi trực tiếp các phương thức trên nó.
Đó là khá nhiều ý chính của nó. Mặc dù về mặt kỹ thuật có một số chi tiết tôi không đề cập đến, chẳng hạn như trong đoạn 'STA', chủ đề của người tạo phải là STA. Nhưng đây là khá nhiều tất cả những gì bạn phải biết để hiểu STA / MTA / NA.
STA (Căn hộ đơn luồng) về cơ bản là khái niệm chỉ có một luồng sẽ tương tác với mã của bạn tại một thời điểm. Các cuộc gọi vào căn hộ của bạn được sắp xếp qua các tin nhắn windows (sử dụng cửa sổ không nhìn thấy). Điều này cho phép các cuộc gọi được xếp hàng và chờ các hoạt động hoàn tất.
MTA (Căn hộ đa luồng) là nơi nhiều luồng có thể hoạt động cùng một lúc và trách nhiệm thuộc về bạn là nhà phát triển để xử lý bảo mật luồng.
Có rất nhiều điều để tìm hiểu về các mô hình luồng trong COM, nhưng nếu bạn gặp khó khăn trong việc hiểu chúng là gì thì tôi sẽ nói rằng hiểu STA là gì và cách thức hoạt động sẽ là nơi khởi đầu tốt nhất vì hầu hết các đối tượng COM là STA.
Chủ đề căn hộ, nếu một chủ đề sống trong cùng một căn hộ với đối tượng mà nó đang sử dụng thì đó là một chủ đề căn hộ. Tôi nghĩ rằng đây chỉ là một khái niệm COM vì nó chỉ là một cách để nói về các đối tượng và chủ đề mà chúng tương tác với.
Mỗi EXE lưu trữ các điều khiển COM hoặc OLE xác định trạng thái căn hộ của nó. Trạng thái căn hộ theo mặc định là STA (và đối với hầu hết các chương trình nên là STA).
STA - Tất cả các điều khiển OLE theo sự cần thiết phải sống trong STA. STA có nghĩa là đối tượng COM của bạn phải luôn được thao tác trên luồng UI và không thể được chuyển sang các luồng khác (giống như bất kỳ thành phần UI nào trong MFC). Tuy nhiên, chương trình của bạn vẫn có thể có nhiều chủ đề.
MTA - Bạn có thể thao tác đối tượng COM trên bất kỳ luồng nào trong chương trình của bạn.
Theo hiểu biết của tôi, 'Căn hộ' được sử dụng để bảo vệ các đối tượng COM khỏi các vấn đề đa luồng.
Nếu một đối tượng COM không an toàn cho luồng, thì nó sẽ khai báo nó là một đối tượng STA. Sau đó, chỉ có chủ đề người tạo ra nó có thể truy cập nó. Chủ đề tạo nên khai báo chính nó như là một chủ đề STA. Dưới mui xe, luồng lưu trữ thông tin STA trong TLS (Lưu trữ cục bộ luồng). Chúng tôi gọi hành vi này là chủ đề đi vào một căn hộ STA. Khi các luồng khác muốn truy cập đối tượng COM này, nó sẽ sắp xếp quyền truy cập vào luồng tạo. Về cơ bản, luồng tạo sử dụng cơ chế thông báo để xử lý các cuộc gọi bị ràng buộc.
Nếu một đối tượng COM là an toàn luồng, nó sẽ khai báo nó là một đối tượng MTA. Đối tượng MTA có thể được truy cập bởi nhiều luồng.
Mã gọi các dll đối tượng COM (ví dụ: để đọc các tệp dữ liệu độc quyền), có thể hoạt động tốt trong giao diện người dùng nhưng bị treo một cách bí ẩn từ một dịch vụ. Lý do là vì các giao diện người dùng .Net 2.0 giả sử STA (an toàn luồng) trong khi các dịch vụ giả định MTA ((trước đó, các dịch vụ giả định STA). Phải tạo một luồng STA cho mỗi cuộc gọi COM trong dịch vụ có thể thêm chi phí đáng kể.