Saya baru saja memperbaiki bug menggunakan ini:
_Thread.SetApartmentState(ApartmentState.STA);
Sekarang saya ingin memahami apa artinya, dan mengapa ini berhasil!
.net
multithreading
Benjol
sumber
sumber
Jawaban:
COM adalah kakek dari .NET. Mereka memiliki tujuan yang cukup tinggi dengannya, salah satu hal yang dilakukan COM tetapi .NET sepenuhnya dilewati adalah memberikan jaminan threading untuk sebuah kelas. Kelas COM dapat mempublikasikan jenis persyaratan penguliran yang dimilikinya. Dan infrastruktur COM memastikan persyaratan tersebut terpenuhi.
Ini sama sekali tidak ada di .NET. Anda dapat menggunakan objek Queue <> misalnya di beberapa utas, tetapi jika Anda tidak mengunci dengan benar, Anda akan memiliki bug parah dalam kode Anda yang sangat sulit untuk didiagnosis.
Detail pasti dari penguliran COM terlalu besar untuk dimuat dalam sebuah kiriman. Saya akan fokus pada pertanyaan spesifik Anda. Sebuah utas yang membuat objek COM harus memberi tahu COM jenis dukungan apa yang ingin diberikannya kepada kelas COM yang memiliki opsi threading terbatas. Sebagian besar class tersebut hanya mendukung apa yang disebut Apartment threading, metode antarmukanya hanya dapat dipanggil dengan aman dari thread yang sama yang membuat instance. Dengan kata lain, mereka mengumumkan "Saya tidak mendukung threading apa pun, harap berhati-hati agar jangan pernah menelepon saya dari utas yang salah". Bahkan jika kode klien benar - benar memanggilnya dari utas lain.
Ada dua macam, STA (Single Threaded Apartment) dan MTA. Ini ditentukan dalam panggilan CoInitializeEx (), fungsi yang harus dipanggil oleh utas apa pun yang melakukan apa pun dengan COM. CLR membuat panggilan itu secara otomatis setiap kali ia memulai utas. Untuk utas startup utama program Anda, ia mendapatkan nilai untuk diteruskan dari atribut [STAThread] atau [MTAThread] pada metode Main () Anda. Default-nya adalah MTA. Untuk utas yang Anda buat sendiri, ini ditentukan oleh panggilan Anda ke SetApartmentState (). Default-nya adalah MTA. Utas threadpool selalu MTA, yang tidak dapat diubah.
Ada banyak kode di Windows yang membutuhkan STA. Contoh penting yang Anda gunakan sendiri adalah Clipboard, Drag + Drop dan dialog shell (seperti OpenFileDialog). Dan banyak kode yang tidak dapat Anda lihat, seperti program Otomasi UI dan kait untuk mengamati pesan. Tak satu pun dari kode itu harus aman untuk thread, pembuatnya akan mengalami kesulitan untuk membuatnya aman tanpa mengetahui di program mana ia akan digunakan. Karenanya, utas UI dari proyek WPF atau Windows Forms harus selalu STA untuk mendukung kode tersebut, seperti halnya utas apa pun yang membuat jendela.
Janji yang Anda buat untuk COM bahwa benang Anda STA namun tidak mengharuskan Anda untuk mengikuti kontrak apartemen single-thread. Mereka cukup kaku dan Anda bisa jadi sulit untuk mendiagnosis masalah saat Anda melanggar kontrak. Persyaratannya adalah Anda tidak pernah memblokir thread selama berapa pun dan Anda memompa loop pesan. Persyaratan terakhir dipenuhi oleh utas UI WPF atau Winforms tetapi Anda harus mengurusnya sendiri jika Anda membuat utas STA Anda sendiri. Diagnosis umum untuk melanggar kontrak adalah kebuntuan.
Ada cukup banyak dukungan built-in CLR untuk mendukung persyaratan ini, membantu Anda menghindari masalah. The kunci pernyataan dan WaitOne () metode pompa pesan loop ketika blok di thread STA. Namun ini hanya menangani persyaratan tidak pernah-blokir, Anda masih perlu membuat loop pesan Anda sendiri. Application.Run () di WPF dan Winforms.
Saya sebelumnya telah menyumbangkan jawaban yang berisi lebih banyak detail tentang pentingnya memiliki loop pesan untuk membuat COM senang. Anda akan menemukan postingannya di sini .
sumber