Masalah Pencabangan Server In-Process
Server dalam proses berjalan tidak memanggil CoInitialize, CoInitializeEx, atau OleInitialize untuk menandai model threadingnya. Untuk objek dalam proses atau berbasis DLL yang mendukung utas, perlu mengatur model utas dalam registri. Model bawaan ketika Anda tidak menentukan model penguliran adalah satu-utas-per-proses. Untuk menentukan model, Anda menambahkan nilai ThreadingModel ke kunci InprocServer32 di registri.
DLL yang mendukung instans objek kelas harus menerapkan 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 pointer ke objek kelasnya saat objek diterapkan di DLL. 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 menerapkannya sedang digunakan, memungkinkan pemanggil untuk membongkarnya dengan aman jika tidak. Panggilan ke CoFreeUnusedLibraries dari utas apa pun selalu dialihkan 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 threading diizinkan antara klien dan objek dalam satu 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 model apartemen berulir, COM mengaktifkan utas "host" model apartemen berulir tunggal di sisi klien. Thread host ini akan membuat objek, dan penunjuk antarmuka akan diarahkan kembali ke wilayah utas bebas milik 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).
Nota
Secara umum, jika Anda merancang antarmuka khusus pada server in-process, Anda juga harus menyediakan kode marshaling untuk itu sehingga COM dapat melakukan pemindahtanganan antarmuka antara lingkungan klien.
COM membantu melindungi akses ke objek yang disediakan oleh DLL berulir tunggal dengan memerlukan akses dari apartemen klien yang sama dengan 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 di apartemen utama klien, memberikan apartemen utama akses langsung ke pointer objek. Panggilan dari apartemen lain menggunakan marshalling interthread untuk berpindah dari proksi ke stub 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 dibongkar 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 instance baru dari fabrik kelas setiap kali DllGetClassObject dipanggil, fabrik kelas tidak perlu memiliki keamanan 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. Model apartemen dari klien yang membuat objek ini akan mendapatkan penunjuk langsung ke objek tersebut. Apartemen klien yang berbeda dari apartemen tempat objek dibuat harus mengakses objek melalui proksi. Proksi ini dibuat ketika klien mengatur akses antarmuka di antara apartemennya.
Saat nilai ThreadingModel dari DLL yang sedang diproses diatur ke "Keduanya", objek yang disediakan oleh DLL ini dapat dibuat dan digunakan secara langsung (tanpa proksi) di apartemen klien satu utas atau multi-utas. Namun, dapat digunakan langsung hanya di dalam apartemen tempat ia dibuat. Agar objek dapat diberikan ke apartemen lain, objek harus diolah terlebih dahulu. 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 fungsiCoCreateFreeThreadedMarshaler. Fungsi ini membuat objek marshaling yang bebas dari ketergantungan thread dan dapat diagregasi dengan objek server yang berada dalam proses yang sama. Ketika apartemen klien dalam proses yang sama membutuhkan akses ke objek di apartemen lain, menggabungkan marshaler yang berbasis utas bebas memberi klien penunjuk langsung ke objek server, bukan 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 penanganan utas bebas adalah objek dengan penanganan utas bebas. Ini menerapkan sinkronisasinya sendiri dan dapat diakses oleh beberapa utas klien secara bersamaan. Server ini tidak mengelola antarmuka di antara utas, sehingga server ini dapat dibuat dan digunakan secara langsung (tanpa proksi) hanya oleh apartemen multithread dalam klien. Apartemen berulir tunggal yang membuatnya akan mengaksesnya melalui proksi.
Topik terkait