STAThread dan multithreading

102

Dari artikel MSDN di STAThread:

Menunjukkan bahwa model penguliran COM untuk aplikasi adalah apartemen berulir tunggal (STA).

(Untuk referensi, itulah keseluruhan artikel .)

Apartemen berulir tunggal ... Oke, itu terlintas di kepalaku. Juga, saya membaca bahwa kecuali aplikasi Anda menggunakan interop COM, atribut ini sebenarnya tidak melakukan apa-apa. Jadi apa sebenarnya fungsinya, dan bagaimana pengaruhnya terhadap aplikasi multithread? Haruskah aplikasi multithread (yang mencakup apa saja dari siapa saja yang menggunakan Timers hingga pemanggilan metode asinkron, bukan hanya threadpool dan sejenisnya) menggunakan MTAThread, bahkan jika itu 'hanya untuk aman'? Apa sebenarnya yang dilakukan STAThread dan MTAThread?

Matthew Scharley
sumber

Jawaban:

60

Threading apartemen adalah konsep COM; jika Anda tidak menggunakan COM, dan tidak ada API yang Anda sebut menggunakan COM "di bawah selimut", maka Anda tidak perlu khawatir tentang apartemen.

Jika Anda benar-benar perlu mengetahui apartemen, maka detailnya bisa menjadi sedikit rumit ; versi yang mungkin terlalu disederhanakan adalah bahwa objek COM yang ditandai sebagai STA harus dijalankan pada STAThread, dan objek COM yang ditandai MTA harus dijalankan pada thread MTA. Dengan menggunakan aturan ini, COM dapat mengoptimalkan panggilan di antara objek yang berbeda ini, menghindari pengubahan urutan jika tidak diperlukan.

Bruce
sumber
7
Itu terlalu disederhanakan. Objek multithread dapat berjalan di utas apa pun. Objek berulir apartemen hanya dapat berjalan di apartemen tempat mereka dibuat.
1800 INFORMATION
28
Panggilan dari objek STA pada utas STA, ke objek MTA, akan beralih ke utas MTA (kecuali objek MTA mengimplementasikan marshaler berulir bebas). Seperti yang saya katakan, detailnya bisa menjadi rumit. (Saya bekerja di tim COM selama beberapa tahun menyeringai )
Bruce
9
Terkadang Anda perlu menyadari hal ini meskipun Anda tidak menggunakan COM secara langsung. Sebuah utas harus menggunakan model Apartemen Berulir Tunggal jika itu menampilkan jendela grafis apa pun. Inilah mengapa [STAThread] selalu ditampilkan di atas metode utama dalam aplikasi formulir windows.
Justin Ethier
6
Tidak bisakah sesuatu seperti dialog Font atau File menggunakan COM tanpa Anda sadari? Saya akan berasumsi bahwa mereka melakukannya secara internal, bukankah itu berarti bahwa hampir semua aplikasi Windows Forms memerlukan STAThread untuk disetel? Maafkan asumsi naif saya karena saya belum benar-benar melakukan pemrograman COM.
Brett Ryan
4
Jawaban yang lebih rinci bagi mereka yang tertarik: stackoverflow.com/questions/4154429/apartmentstate-for-dummies
jgauffin
3

Apa yang dilakukannya itu memastikan yang CoInitializedisebut menentukan COINIT_APARTMENTTHREADED sebagai parameter. Jika Anda tidak menggunakan komponen COM atau kontrol ActiveX, itu tidak akan berpengaruh sama sekali pada Anda. Jika Anda melakukannya maka itu agak penting.

Kontrol yang berulir apartemen secara efektif berulir tunggal, panggilan yang dilakukan hanya dapat diproses di apartemen tempat mereka dibuat.

Beberapa detail lebih lanjut dari MSDN:

Objek yang dibuat di apartemen single-threaded (STA) menerima panggilan metode hanya dari thread apartemen mereka, sehingga panggilan dibuat berseri dan hanya sampai di batas antrian pesan (ketika fungsi Win32 PeekMessage atau SendMessage dipanggil).

Objek yang dibuat pada utas COM di apartemen multithread (MTA) harus dapat menerima panggilan metode dari utas lain kapan saja. Anda biasanya akan menerapkan beberapa bentuk kontrol konkurensi dalam kode objek multithread menggunakan primitif sinkronisasi Win32 seperti bagian kritis, semaphore, atau mutex untuk membantu melindungi data objek.

Ketika sebuah objek yang dikonfigurasi untuk berjalan di apartemen berulir netral (NTA) dipanggil oleh utas yang ada di STA atau MTA, utas itu ditransfer ke NTA. Jika utas ini kemudian memanggil CoInitializeEx, panggilan gagal dan mengembalikan RPC_E_CHANGED_MODE.

1800 INFORMASI
sumber
Artikel MSDN sangat membantu dari perspektif COM, tetapi dapatkah Anda memberi tahu saya ketika panggilan NET. CoInitialize()Menanggapi STAThreadatribut / ApartmentState? Catatan: Artikel di MSDN ada di sini: Fungsi CoInitializeEx .
jrh
Apakah thread-> SetApartment digunakan secara CoInitialize()internal? Saya menelusuri Atribut STAThread sampai ke bawah tetapi jejaknya menjadi dingin (saya tidak dapat menemukan sumbernya Thread::SetApartment). Apakah kelas Thread dari thread.h (COM thread.h) didokumentasikan di mana saja? Apakah itu MFC, ATL, atau yang lainnya?
jrh
@jrh Saya tidak tahu lebih detail dari itu maaf
INFORMASI 1800
-15

STAThread ditulis sebelum fungsi Utama dari Proyek C # GUI. Itu tidak melakukan apa-apa selain memungkinkan program untuk membuat satu utas.

Zeinth
sumber