2012-07-03 44 views
14

Tôi đã gặp vấn đề này nhiều lần trong khi phát triển trong C#. Tôi sẽ là một hạnh phúc mã hóa cùng, đi qua đối tượng qua lại giữa các chủ đề và những gì không, sau đó tất cả của một đột ngột tôi nhận được lỗi quen thuộc này:Tại sao một số đối tượng không thể truy cập từ các chủ đề khác nhau?

"The calling thread cannot access this object because a different thread owns it."

Vâng, ok, tôi đã xử lý nó trước, đặc biệt là với các đối tượng trên luồng GUI. Bạn chỉ cần viết một số mã bổ sung cho chương trình xung quanh vấn đề cụ thể. Nhưng mỗi lần trong khi tôi đi qua một đối tượng đó là bằng mọi cách bình thường, nhưng nó không giống như bị truy cập bởi các chủ đề khác nhau.

EDIT Tôi đã nhầm lẫn trong bài đăng gốc về đối tượng đã gây ra ngoại lệ truy cập. Đó là KHÔNG IPAddress, thay vì System.Printing.PrintQueue. mà tôi đang sử dụng để lấy địa chỉ IP. Đây là đối tượng mà bạn không thể đánh giá từ hơn 1 luồng.

Tất cả các lớp học của tôi mà tôi đã viết chưa bao giờ gặp sự cố này. Tôi thậm chí không biết làm thế nào tôi sẽ thực hiện điều này bản thân mình. Bạn có cần phải giữ một biến thành viên với ID luồng đã tạo ra bạn, và sau đó kiểm tra chuỗi hiện tại dựa vào đó trên mọi thuộc tính và truy cập phương thức không? Điều đó có vẻ điên rồ. Tại sao Microsoft lại quyết định rằng ..... "OK ... PrintQueue, chắc chắn không thể chia sẻ giữa các chủ đề. Nhưng những lớp khác .... họ sẽ tốt để đi."

Tại sao một số đối tượng bị chặn truy cập nhiều chuỗi?

+2

Hãy nghĩ về giải pháp thay thế: bất kỳ chuỗi nào cũng có thể truy cập bất kỳ đối tượng nào theo ý thích. Bây giờ đối tượng đó hoặc là phụ thuộc vào accessor để xử lý đúng đắn các mối quan tâm luồng, hoặc nó phải viết một bó mã phụ để đảm bảo rằng nó an toàn cho các trình truy cập từ nhiều luồng. Tùy chọn 1 là không thực tế, và tùy chọn 2 là rất nhiều công việc. Vì vậy, quyết định đã được thực hiện để đi với tùy chọn 3: không cho phép người truy cập từ nhiều chủ đề. – dlev

+1

Xấu Microsoft. Xấu. –

+1

Dường như việc xử lý rác thải C# khóa các biến nhất định tùy thuộc vào cách chúng được sử dụng. Tôi đã không bao giờ phải đối phó với điều này, nhưng một cách tốt để thử và sửa chữa vấn đề này là đặt biến của bạn thành một chủ sở hữu tĩnh nếu bạn có kế hoạch chia sẻ chúng giữa các chủ đề. Một luồng đọc chủ đề khác viết. Bạn có thể cần phải làm một số khóa để đảm bảo rằng bạn không có va chạm trên viết nếu cả hai người trong số họ cần phải thay đổi giá trị. –

Trả lời

3

Tôi nghĩ điều này có thể giải thích mọi thứ khá tốt, tôi nghĩ điều này đặc biệt liên quan đến COM.

http://msdn.microsoft.com/en-us/library/ms693344%28v=vs.85%29

riêng.

In general, the simplest way to view the COM threading architecture is to think of all the COM objects in the process as divided into groups called apartments. A COM object lives in exactly one apartment, in the sense that its methods can legally be directly called only by a thread that belongs to that apartment. Any other thread that wants to call the object must go through a proxy.

There are two types of apartments: single-threaded apartments, and multithreaded apartments.

Single-threaded apartments consist of exactly one thread, so all COM objects that live in a single-threaded apartment can receive method calls only from the one thread that belongs to that apartment. All method calls to a COM object in a single-threaded apartment are synchronized with the windows message queue for the single-threaded apartment's thread. A process with a single thread of execution is simply a special case of this model.

Multithreaded apartments consist of one or more threads, so all COM objects that live in an multithreaded apartment can receive method calls directly from any of the threads that belong to the multithreaded apartment. Threads in a multithreaded apartment use a model called free-threading. Calls to COM objects in a multithreaded apartment are synchronized by the objects themselves.

+2

Vì vậy, bạn ngụ ý rằng đối tượng System.Printing.PrintQueue thực sự là một đối tượng COM STA, và đó là lý do tại sao nó không thể được xúc động bởi các chủ đề khác? Từ xem tài liệu System.Printing.PrintQueue, làm thế nào tôi có thể nói rằng đây là một đối tượng COM STA? – Ultratrunks

+0

Thú vị. Tôi nghĩ rằng http://msdn.microsoft.com/en-us/library/5s8ee185.aspx bổ sung cho câu trả lời ở trên (và cũng giải thích tại sao Ultratrunks gặp phải các vấn đề như vậy kết hợp với lập trình GUI). – jpe

+0

@Ultratrunks Tôi khá chắc chắn rằng lớp là trình bao bọc COM vì nó truy cập hàng đợi in. Tuy nhiên, tôi không biết làm thế nào để biết trước được STA là gì. Có một phần an toàn chủ đề cho các lớp trong MSDN, nhưng tôi không thấy những gì tôi mong đợi để xem trong đó. –

Các vấn đề liên quan