Thread in C# - Part 9: Apartments and Windows Forms  
 

(Post 30/10/2007) Apartment threading is an automatic thread-safety regime, closely allied to COM – Microsoft's legacy Component Object Model. While .NET largely breaks free of legacy threading models, there are times when it still crops up because of the need to interoperate with older APIs. Apartment threading is most relevant to Windows Forms, because much of Windows Forms uses or wraps the long-standing Win32 API – complete with its apartment heritage.

An apartment is a logical "container" for threads. Apartments come in two sizes – "single" and "multi". A single-threaded apartment contains just one thread; multi-threaded apartments can contain any number of threads. The single-threaded model is the more common and interoperable of the two.

As well as containing threads, apartments contain objects. When an object is created within an apartment, it stays there all its life, forever house-bound along with the resident thread(s). This is similar to an object being contained within a .NET synchronization context, except that a synchronization context does not own or contain threads. Any thread can call upon an object in any synchronization context – subject to waiting for the exclusive lock. But objects contained within an apartment can only be called upon by a thread within the apartment.

Imagine a library, where each book represents an object. Borrowing is not permitted – books created in the library stay there for life. Furthermore, let's use a person to represent a thread.

A synchronization context library allows any person to enter, as long as only one person enters at a time. Any more, and a queue forms outside the library.

An apartment library has resident staff – a single librarian for a single-threaded library, and whole team for a multi-threaded library. No-one is allowed in other than members of staff – a patron wanting to perform research must signal a librarian, then ask the librarian to do the job! Signaling the librarian is called marshalling – the patron marshals the method call over to a member of staff (or, the member of staff!) Marshalling is automatic, and is implemented at the librarian-end via a message pump – in Windows Forms, this is the mechanism that constantly checks for keyboard and mouse events from the operating system. If messages arrive too quickly to be processed, they enter a message queue, so they can be processed in the order they arrive.

Specifying an Apartment Model

A .NET thread is automatically assigned an apartment upon entering apartment-savvy Win32 or legacy COM code. By default, it will be allocated a multi-threaded apartment, unless one requests a single-threaded apartment as follows:

Thread t = new Thread (...);
t.SetApartmentState (ApartmentState.STA);

One can also request that the main thread join a single-threaded apartment using the STAThread attribute on the main method:

class Program {
[STAThread]
static void Main() {
...

Apartments have no effect while executing pure .NET code. In other words, two threads with an apartment state of STA can simultaneously call the same method on the same object, and no automatic marshalling or locking will take place. Only when execution hits unmanaged code can they kick in.

The types in the System.Windows.Forms namespace extensively call Win32 code designed to work in a single-threaded apartment. For this reason, a Windows Forms program should have have the [STAThread] attribute on its main method, otherwise one of two things will occur upon reaching Win32 UI code:

  • it will marshal over to a single-threaded apartment
  • it will crash

Control.Invoke

In a multi-threaded Windows Forms application, it's illegal to call a method or property on a control from any thread other than the one that created it. All cross-thread calls must be explicitly marshalled to the thread that created the control (usually the main thread), using the Control.Invoke or Control.BeginInvoke method. One cannot rely on automatic marshalling because it takes place too late – only when execution gets well into unmanaged code, by which time plenty of internal .NET code may already have run on the "wrong" thread – code which is not thread-safe.

An excellent solution to managing worker threads in Windows Forms applications is to use BackgroundWorker. This class wraps worker threads that need to report progress and completion, and automatically calls Control.Invoke as required.

(Sưu tầm)


 
 

 
     
 
Công nghệ khác:


Thread in C# - Part 8: Synchronization ContextsThread in C# - Part 7: Wait Handles
Thread in C# - Part 6: Thread StateThread in C# - Part 5: Interrupt and Abort
Thread in C# - Part 4: Locking and Thread SafetyThread in C# - Part 3: Synchronization Essentials
  Xem tiếp    
 
Lịch khai giảng của hệ thống
 
Ngày
Giờ
T.Tâm
TP Hồ Chí Minh
Hà Nội
 
   
New ADSE - Nhấn vào để xem chi tiết
Mừng Sinh Nhật Lần Thứ 20 FPT-APTECH
Nhấn vào để xem chi tiết
Bảng Vàng Thành Tích Sinh Viên FPT APTECH - Nhấn vào để xem chi tiết
Cập nhật công nghệ miễn phí cho tất cả cựu sinh viên APTECH toàn quốc
Tiết Thực Vì Cộng Đồng
Hội Thảo CNTT
Những khoảnh khắc không phai của Thầy Trò FPT-APTECH Ngày 20-11