Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Warning
STA iş parçacıklarında async/await ve bloklayan çağrılarla kilitlenme riski: Yönetilen kodda (.NET), STA ileti döngüsü COM çağrılarının dağıtılması için kritik öneme sahiptir. Bir STA iş parçacığını Task.Wait(), Task.Result, Thread.Sleep() veya ManualResetEvent.WaitOne() ile engellemek, COM geri çağırmalarının ve apartmanlar arası çağrıların tamamlanmasını önler ve kilitlenmeye neden olur.
// ❌ DEADLOCK — blocks the STA message loop
[STAThread]
static void Main()
{
var result = GetDataAsync().Result; // Deadlock: awaited continuation
// can't post back to this STA thread
}
// ✅ Correct — use async entry point or pump messages
[STAThread]
static async Task Main()
{
var result = await GetDataAsync(); // continuation resumes on STA via SynchronizationContext
}
await kullanamıyorsanız, STA iş parçacıklarında ham bekleme ilkel yapıları yerine CoWaitForMultipleHandles (yerel) veya bir sevk çerçevesi/ileti pompası (yönetilen) kullanın.
Tek iş parçacıklı daireleri (daire modeli işlemi) kullanmak, eşzamanlı olarak çalışan birden çok nesneyle ilgilenmek için ileti tabanlı bir paradigma sunar. Bir iş parçacığının, zaman alan bir işlemin tamamlanmasını beklerken başka bir iş parçacığının yürütülmesine olanak tanıması sayesinde daha verimli kod yazmanızı sağlar.
Bir apartman modeli işlemi olarak başlatılan ve pencere iletilerini alan ve dağıtan bir işlemdeki her iş parçacığı, tek iş parçacıklı bir daire iş parçacığıdır. Her iplik kendi dairesi içinde yaşar. Bir apartment içinde, arabirim işaretçileri marshaling olmadan aktarılabilir; bu nedenle, aynı tek iş parçacıklı apartment içindeki tüm nesneler birbiriyle doğrudan iletişim kurar.
Tümü aynı iş parçacığında yürütülen ve bu nedenle zaman uyumlu yürütmeye sahip olması gereken ilişkili nesnelerin mantıksal gruplandırması, aynı tek iş parçacıklı daire iş parçacığında yaşayabilir. Ancak, bir daire modeli nesnesi birden fazla iş parçacığında bulunamaz. Diğer iş parçacıklarındaki nesnelere çağrılar, sahip olan iş parçacığı bağlamında yapılmalıdır, bu nedenle dağıtılmış COM bir ara sunucuyu çağırdığınızda iş parçacıklarını sizin için otomatik olarak değiştirir.
İşlemler arası ve iş parçacıkları arası modeller benzerdir. Aynı işlem içinde bir arabirim işaretçisini başka bir apartmandaki bir nesneye (başka bir iş parçacığında) geçirmek gerektiğinde, farklı işlemlerdeki nesnelerin işaretçileri işlem sınırları arasında geçirmek için kullandığı aynı sıralama modelini kullanırsınız. Standart sıralama nesnesine bir işaretçi alarak, arabirim işaretçilerini işlemler arasında yaptığınız gibi iş parçacığı sınırları (daireler arasında) arasında sıralayabilirsiniz. (Arabirim işaretçileri daireler arasında geçirildiğinde sıralanmalıdır.)
Tek iş parçacıklı daireler için kurallar basittir, ancak bunları dikkatle izlemek önemlidir:
- Her nesne yalnızca bir iş parçacığında (tek iş parçacıklı bir dairede) yaşamalıdır.
- Her iş parçacığı için COM kitaplığını başlatın.
- Tüm işaretçileri daireler arasında geçirirken nesnelere göre sırala.
- Tek iş parçacıklı her dairenin, aynı işlem içindeki diğer işlemlerden ve dairelerden gelen çağrıları işlemek için bir ileti döngüsü olmalıdır. Nesneleri olmayan tek iş parçacıklı daireler (yalnızca istemci) ayrıca bazı uygulamaların kullandığı yayın iletilerini göndermek için bir ileti döngüsüne de ihtiyaç duyar.
- DLL tabanlı veya işlem içi nesneler COM başlatma işlevlerini çağırmaz; bunun yerine, iş parçacığı modelini kayıt defterindeki InprocServer32 anahtarı altında ThreadingModel named-value ile kaydederler. Apartman modeline duyarlı nesnelerin de DLL giriş noktalarını dikkatli bir şekilde yazması gerekir. İşlem içi sunucularda iş parçacığı oluşturma için dikkat edilmesi gereken özel noktalar vardır. Daha fazla bilgi için bkz. In-Process Sunucuda İş Parçacığı Sorunları.
Birden çok nesne tek bir iş parçacığında yaşayabilse de, hiçbir apartman modeli nesnesi birden fazla iş parçacığında yaşayamaz.
İstemci işleminin veya işlem dışı sunucunun her iş parçacığı CoInitialize çağırmalı ya da CoInitializeEx çağırmalı ve dwCoInit parametresi için COINIT_APARTMENTTHREADED belirtmelidir. Ana apartment, CoInitializeEx işlevini ilk çağıran iş parçacığıdır. İşlem içi sunucular hakkında bilgi için In-Process Sunucu İş Parçacığı Sorunları bölümüne bakın.
Bir nesneye yapılan tüm çağrılar iş parçacığında (kendi dairesi içinde) yapılmalıdır. Bir nesneyi doğrudan başka bir iş parçacığından çağırmak yasaktır; nesnelerin bu serbest iş parçacığı modeliyle kullanılması, uygulamalarda sorunlara yol açabilir. Bu kuralın anlamı, nesnelere işaret eden tüm işaretçilerin daireler arasında aktarıldığında marshal edilmesi gerektiğidir. COM bu amaçla aşağıdaki iki işlevi sağlar:
- CoMarshalInterThreadInterfaceInStream, bir arabirimi çağırana döndürülen bir akış nesnesi içine marşalleştirir.
- CoGetInterfaceAndReleaseStream bir arabirim işaretçisini akış nesnesinden kaldırır ve serbest bırakır.
Bu işlevler, CoMarshalInterface ve CoUnmarshalInterface işlevlerine yapılan, MSHCTX_INPROC bayrağının kullanılmasını gerektiren çağrıları sarmalar.
Genel olarak, sıralama COM tarafından otomatik olarak gerçekleştirilir. Örneğin, başka bir iş parçacığı bölümündeki bir nesneye ait proxy üzerinde yapılan bir yöntem çağrısında bir arabirim işaretçisi parametre olarak geçirildiğinde veya CoCreateInstance çağrıldığında, COM marshaling işlemini otomatik olarak gerçekleştirir. Ancak, uygulama yazıcısının normal COM mekanizmalarını kullanmadan daireler arasında arabirim işaretçileri ilettiği bazı özel durumlarda, yazıcının hazırlamayı el ile işlemesi gerekir.
Bir işlemde bir apartment'ın (Apartment 1) bir arabirim işaretçisi varsa ve başka bir apartment'ın (Apartment 2) bunu kullanması gerekiyorsa, Apartment 1'in arabirimi marshal etmek için CoMarshalInterThreadInterfaceInStream çağrısını yapması gerekir. Bu işlev tarafından oluşturulan akış iş parçacığı açısından güvenlidir ve 2. Daire tarafından erişilebilen bir değişkende depolanmalıdır. Apartment 2, arabirimin sıralamasını çözmek için bu akışı CoGetInterfaceAndReleaseStream işlevine geçirmelidir ve bunun aracılığıyla arabirime erişebileceği bir vekil işaretçisi geri alır. İstemci COM ile ilgili tüm işlemlerini tamamlayana kadar ana apartment etkin kalmalıdır (çünkü İşlem İçi Sunucu İş Parçacığı Sorunları bölümünde açıklandığı gibi, bazı işlem içi nesneler ana apartment içine yüklenir). Bu şekilde bir nesne iş parçacıkları arasında aktarıldıktan sonra, arabirim işaretçilerini parametre olarak geçirmek çok kolaydır. Bu şekilde, dağıtılmış COM uygulama için sıralama ve iş parçacığı geçişini yapar.
Aynı işlem içindeki diğer işlemlerden ve dairelerden gelen çağrıları işlemek için, tek iş parçacıklı her dairenin bir ileti döngüsü olmalıdır. Bu, iş parçacığının iş işlevinin GetMessage/DispatchMessage döngüsüne sahip olması gerektiği anlamına gelir. İş parçacıkları arasında iletişim kurmak için diğer eşitleme temel bilgileri kullanılıyorsa, MsgWaitForMultipleObjects işlevi hem iletileri hem de iş parçacığı eşitleme olaylarını beklemek için kullanılabilir. Bu işlevin belgelerinde bu tür bir birleşim döngüsü örneği vardır.
COM, tek iş parçacıklı her dairede "OleMainThreadWndClass" Windows sınıfını kullanarak gizli bir pencere oluşturur. Bir nesneye yapılan çağrı, bu gizli pencereye bir pencere iletisi olarak iletilir. Nesnenin apartment’ı iletiyi alıp gönderdiğinde, gizli pencere iletiyi alacaktır. Pencere yordamı daha sonra nesnenin ilgili arabirim yöntemini çağırır.
Birden çok istemci bir nesneyi çağırdığında, çağrılar ileti kuyruğunda kuyruğa alınır ve dairesi iletileri her aldığında ve dağıttığında nesne bir çağrı alır. Çağrılar COM tarafından senkronize edildiği ve her zaman nesnenin apartment’ına ait iş parçacığı tarafından işlendiği için, nesnenin arabirim uygulamalarının senkronizasyon sağlaması gerekmez. Tek iş parçacıklı daireler, gerektiğinde çağrıları iptal etmelerine veya pencere iletileri almalarına izin vermek için IMessageFilter uygulayabilir.
Nesne, arabirim yöntemi uygulamalarından biri mesajları alıp dağıtırsa veya başka bir iş parçacığına ORPC çağrısı yaparsa ve böylece nesneye (aynı apartment tarafından) başka bir çağrının iletilmesine neden olursa yeniden girilebilir. OLE aynı iş parçacığında yeniden giriş yapılmasını engellemez, ancak iş parçacığı güvenliğini sağlamaya yardımcı olabilir. Bu, bir ileti işlenirken iletileri alıp dağıtan bir pencere yordamının yeniden girme yöntemiyle aynıdır. Ancak, başka bir tek iş parçacıklı apartment sunucusunu çağıran işlem dışı bir tek iş parçacıklı apartment sunucusunu çağırmak, ilk sunucuya yeniden girilmesine olanak tanır.
İlgili konular