Masalah Utas Server Dalam Proses
Server dalam proses tidak memanggil CoInitialize, CoInitializeEx, atau OleInitialize untuk menandai model utasnya. Untuk objek berbasis DLL atau dalam proses yang sadar utas, Anda perlu mengatur model utas dalam registri. Model default saat Anda tidak menentukan model utas adalah single-thread-per-process. Untuk menentukan model, Anda menambahkan nilai ThreadingModel ke kunci InprocServer32 di registri.
DLL yang mendukung instansiasi objek kelas harus mengimplementasikan dan mengekspor fungsi DllGetClassObject dan DllCanUnloadNow. Ketika klien menginginkan instans kelas yang didukung DLL, panggilan ke CoGetClassObject (baik secara langsung atau melalui panggilan ke CoCreateInstance) memanggil DllGetClassObject untuk mendapatkan penunjuk ke objek kelasnya saat objek diimplementasikan dalam DLL. Oleh karena itu, DllGetClassObject harus dapat memberikan beberapa objek kelas atau objek aman utas tunggal (pada dasarnya hanya menggunakan InterlockedIncrement/InterlockedDecrement pada jumlah referensi internal mereka).
Seperti namanya, DllCanUnloadNow dipanggil untuk menentukan apakah DLL yang mengimplementasikannya sedang digunakan, memungkinkan pemanggil untuk membongkarnya dengan aman jika tidak. Panggilan ke CoFreeUnusedLibraries dari utas apa pun selalu merutekan melalui utas apartemen utama untuk memanggil DllCanUnloadNow.
Seperti server lain, server dalam proses dapat berupa utas tunggal, utas apartemen, atau utas bebas. Server ini dapat digunakan oleh klien OLE apa pun, terlepas dari model utas yang digunakan oleh klien tersebut.
Semua kombinasi interoperabilitas model utas diizinkan antara klien dan objek dalam proses. Interaksi antara klien dan objek dalam proses yang menggunakan model utas yang berbeda persis seperti interaksi antara klien dan server di luar proses. Untuk server dalam proses, ketika model utas klien dan server dalam proses berbeda, COM harus menginterposisi dirinya sendiri antara klien dan objek.
Ketika objek dalam proses yang mendukung model utas tunggal dipanggil secara bersamaan oleh beberapa utas klien, COM tidak dapat mengizinkan utas klien untuk langsung mengakses antarmuka objekâ €"objek tidak dirancang untuk akses tersebut. Sebaliknya, COM harus memastikan bahwa panggilan disinkronkan dan hanya dilakukan oleh utas klien yang membuat objek. Oleh karena itu, COM membuat objek di apartemen utama klien dan mengharuskan semua apartemen klien lainnya untuk mengakses objek dengan menggunakan proksi.
Ketika apartemen berulir bebas (model apartemen multithreaded) di klien membuat server dalam proses berulir apartemen, COM memutar utas "host" model apartemen berulir tunggal di klien. Utas host ini akan membuat objek, dan penunjuk antarmuka akan dinaikkan kembali ke apartemen utas bebas klien. Demikian pula, ketika apartemen berulir tunggal di klien model apartemen membuat server dalam proses berulir bebas, COM memutar utas host utas bebas (apartemen multithreaded tempat objek akan dibuat dan kemudian dirusak kembali ke apartemen klien berulir tunggal).
Catatan
Secara umum, jika Anda merancang antarmuka kustom di server dalam proses, Anda juga harus menyediakan kode marshaling untuk itu sehingga COM dapat melakukan marshal antarmuka antara apartemen klien.
COM membantu melindungi akses ke objek yang disediakan oleh DLL berulir tunggal dengan memerlukan akses dari apartemen klien yang sama tempat mereka dibuat. Selain itu, semua titik masuk DLL (seperti DllGetClassObject dan DllCanUnloadNow) dan data global harus selalu diakses oleh apartemen yang sama. COM membuat objek seperti itu di apartemen utama klien, memberikan akses langsung apartemen utama ke pointer objek. Panggilan dari apartemen lain menggunakan marshaling interthread untuk pergi dari proksi ke rak di apartemen utama dan kemudian ke objek . Ini memungkinkan COM untuk menyinkronkan panggilan ke objek. Panggilan interthread lambat, jadi disarankan agar server ini ditulis ulang untuk mendukung beberapa apartemen.
Seperti server dalam proses berulir tunggal, objek yang disediakan oleh DLL model apartemen harus diakses oleh apartemen klien yang sama tempatnya dibuat. Namun, objek yang disediakan oleh server ini dapat dibuat di beberapa apartemen klien, sehingga server harus menerapkan titik masuknya (seperti DllGetClassObject dan DllCanUnloadNow) untuk penggunaan multithreaded. Misalnya, jika dua apartemen klien mencoba membuat dua instans objek dalam proses secara bersamaan, DllGetClassObject dapat dipanggil secara bersamaan oleh kedua apartemen. DllCanUnloadNow harus ditulis agar DLL tidak membongkar saat kode masih dijalankan di DLL.
Jika DLL hanya menyediakan satu instans pabrik kelas untuk membuat semua objek, implementasi pabrik kelas juga harus dirancang untuk penggunaan multithreaded, karena akan diakses oleh beberapa apartemen klien. Jika DLL membuat instans baru pabrik kelas setiap kali DllGetClassObject dipanggil, pabrik kelas tidak perlu aman untuk utas.
Objek yang dibuat oleh pabrik kelas tidak perlu aman utas. Setelah dibuat oleh utas, objek selalu diakses melalui utas tersebut dan semua panggilan ke objek disinkronkan oleh COM. Apartemen model apartemen klien yang membuat objek ini akan mendapatkan penunjuk langsung ke objek. Apartemen klien yang berbeda dari apartemen tempat objek dibuat harus mengakses objek melalui proksi. Proksi ini dibuat ketika klien melakukan marshal antarmuka antara apartemennya.
Ketika nilai DLL ThreadingModel dalam proses diatur ke "Keduanya", objek yang disediakan oleh DLL ini dapat dibuat dan digunakan secara langsung (tanpa proksi) di apartemen klien berulir tunggal atau multithreaded. Namun, dapat digunakan langsung hanya di dalam apartemen tempat ia dibuat. Untuk memberikan objek ke apartemen lain, objek harus di-marshal. Objek DLL harus menerapkan sinkronisasinya sendiri dan dapat diakses oleh beberapa apartemen klien secara bersamaan.
Untuk mempercepat performa untuk akses utas bebas ke objek DLL dalam proses, COM menyediakan fungsi CoCreateFreeThreadedMarshaler. Fungsi ini membuat objek marshaling berulir bebas yang dapat diagregasi dengan objek server dalam proses. Ketika apartemen klien dalam proses yang sama membutuhkan akses ke objek di apartemen lain, mengagregasi marshaler utas bebas memberi klien penunjuk langsung ke objek server, daripada ke proksi, ketika klien melakukan marshal antarmuka objek ke apartemen yang berbeda. Klien tidak perlu melakukan sinkronisasi apa pun. Ini hanya berfungsi dalam proses yang sama; marshaling standar digunakan untuk referensi ke objek yang dikirim ke proses lain.
Objek yang disediakan oleh DLL dalam proses yang hanya mendukung utas gratis adalah objek utas bebas. Ini menerapkan sinkronisasinya sendiri dan dapat diakses oleh beberapa utas klien secara bersamaan. Server ini tidak marshal antarmuka antara utas, sehingga server ini dapat dibuat dan digunakan secara langsung (tanpa proksi) hanya oleh apartemen multithreaded di klien. Apartemen berulir tunggal yang membuatnya akan mengaksesnya melalui proksi.
Topik terkait