In-Process Servertrådsproblem
En processerver anropar inte CoInitialize, CoInitializeExeller OleInitialize för att markera sin trådningsmodell. För trådmedvetna DLL-baserade eller processbaserade objekt måste du ange trådmodellen i registret. Standardmodellen när du inte anger någon trådmodell är en tråd per process. Om du vill ange en modell lägger du till värdet ThreadingModel till InprocServer32-nyckeln i registret.
DLL:er som stöder instansiering av ett klassobjekt måste implementera och exportera funktionerna DllGetClassObject och DllCanUnloadNow. När en klient vill ha en instans av klassen som DLL stöder anropar ett anrop till CoGetClassObject (antingen direkt eller via ett anrop till CoCreateInstance) DllGetClassObject för att få en pekare till dess klassobjekt när objektet implementeras i en DLL. DllGetClassObject bör därför kunna ge bort flera klassobjekt eller ett enda trådsäkert objekt (i stort sett bara med InterlockedIncrement/InterlockedDecrement på deras interna referensantal).
Som namnet antyder anropas DllCanUnloadNow för att avgöra om DLL:en som implementerar den används, vilket gör det möjligt för anroparen att ta bort den på ett säkert sätt om den inte är det. Anrop till CoFreeUnusedLibraries från vilka trådar som helst dirigeras alltid genom huvudtråden i huvudlägenheten för att anropa DllCanUnloadNow.
Precis som andra servrar kan processerver vara enkeltrådade, lägenhetstrådade eller fritrådade. Dessa servrar kan användas av valfri OLE-klient, oavsett vilken trådmodell som används av klienten.
Alla kombinationer av trådningsmodellens samverkan tillåts mellan klienter och processobjekt. Interaktion mellan en klient och ett processobjekt som använder olika trådmodeller är precis som interaktionen mellan klienter och servrar som inte är processer. För en processerver, när trådningsmodellen för klienten och processervern skiljer sig åt, måste COM samla sig mellan klienten och objektet.
När ett processobjekt som stöder entrådad modell anropas samtidigt av flera trådar i en klient, kan COM inte tillåta att klienttrådarna kommer åt objektets gränssnitt direkt" objektet har inte utformats för sådan åtkomst. I stället måste COM se till att anrop synkroniseras och endast görs av klienttråden som skapade objektet. Därför skapar COM objektet i klientens huvudlägenhet och kräver att alla andra klientlägenheter får åtkomst till objektet med hjälp av proxyservrar.
När en fritrådad lägenhet (flertrådad lägenhetsmodell) i en klient skapar en lägenhetstrådad processserver, snurrar COM upp en entrådad lägenhetsmodell "värd" tråd i klienten. Den här värdtråden skapar objektet och gränssnittspekaren konverteras tillbaka till klientens fritrådade lägenhet. På samma sätt, när en enkeltrådad lägenhet i en lägenhetsmodellklient skapar en fritrådad processserver, snurrar COM upp en fritrådad värdtråd (flertrådad lägenhet där objektet kommer att skapas och sedan konverteras tillbaka till klientens entrådade lägenhet).
Notera
Om du utformar ett anpassat gränssnitt på en pågående server bör du i allmänhet även ange kod för marskalkering för den så att COM kan konvertera gränssnittet mellan klientlägenheter.
COM skyddar åtkomsten till objekt som tillhandahålls av en enkeltrådad DLL genom att kräva åtkomst från samma klientlägenhet där de skapades. Dessutom bör alla DLL-startpunkter (som DllGetClassObject och DllCanUnloadNow) och globala data alltid nås av samma lägenhet. COM skapar sådana objekt i klientens huvudlägenhet, vilket ger huvudlägenheten direkt åtkomst till objektets pekare. Samtal från de andra lägenheterna använder interthread marshaling för att gå från proxyn till stub i huvudlägenheten och sedan till objektet. Detta gör att COM kan synkronisera anrop till objektet. Interthread-anrop är långsamma, så det rekommenderas att dessa servrar skrivs om för att stödja flera lägenheter.
Precis som en entrådad processserver måste ett objekt som tillhandahålls av en DLL för lägenhetsmodell nås av samma klientlägenhet som det skapades från. Objekt som tillhandahålls av den här servern kan dock skapas i flera lägenheter i klienten, så servern måste implementera sina startpunkter (till exempel DllGetClassObject och DllCanUnloadNow) för flertrådad användning. Om två lägenheter i en klient till exempel försöker skapa två instanser av det processbaserade objektet samtidigt kan DllGetClassObject anropas samtidigt av båda lägenheterna. DllCanUnloadNow måste skrivas så att DLL:en inte tas bort medan koden fortfarande körs i DLL-filen.
Om DLL:en endast tillhandahåller en instans av klassfabriken för att skapa alla objekt måste implementeringen av klassfabriken också vara utformad för flertrådad användning, eftersom den kommer att nås av flera klientlägenheter. Om DLL:n skapar en ny instans av klassfabriken varje gång DllGetClassObject anropas, behöver klassfabriken inte vara trådsäker.
Objekt som klassfabriken skapar behöver inte vara trådsäkra. När objektet har skapats av en tråd nås det alltid via den tråden och alla anrop till objektet synkroniseras av COM. Lägenhetsmodelllägenheten för en klient som skapar det här objektet får en direkt pekare till objektet. Klientlägenheter som skiljer sig från den lägenhet där objektet skapades måste komma åt objektet via proxyservrar. Dessa proxyservrar skapas när klienten konverterar gränssnittet mellan sina lägenheter.
När en processbaserad DLL-ThreadingModel värdet är inställt på "Båda", kan ett objekt som tillhandahålls av denna DLL skapas och användas direkt (utan proxy) i entrådade eller flertrådade klientlägenheter. Den kan dock endast användas direkt i den lägenhet där den skapades. Om du vill ge objektet till någon annan lägenhet måste objektet konverteras. DLL-objektet måste implementera sin egen synkronisering och kan nås av flera klientlägenheter samtidigt.
För att påskynda prestanda för fritrådad åtkomst till processbaserade DLL-objekt tillhandahåller COM funktionen CoCreateFreeThreadedMarshaler. Den här funktionen skapar ett fritrådat marskalkningsobjekt som kan aggregeras med ett processbaserat serverobjekt. När klientens lägenhet i samma process behöver åtkomst till ett objekt i ett annat lägenhetsutrymme, ger aggregering av den fritrådade marskalkaren klienten en direktpekare till serverobjektet, snarare än till en proxy, när klienten överför objektets gränssnitt till ett annat lägenhetsutrymme. Klienten behöver inte utföra någon synkronisering. Detta fungerar bara inom samma process. standard marshaling används för en referens till objektet som skickas till en annan process.
Ett objekt som tillhandahålls av en processbaserad DLL som endast stöder fri trådning är ett fritrådat objekt. Den implementerar sin egen synkronisering och kan nås av flera klienttrådar samtidigt. Den här servern hanterar inte gränssnitt mellan trådar, så den här servern kan endast skapas och användas direkt (utan proxy) av flertrådade element i en klient. Entrådade lägenheter som skapar den kommer att komma åt den via en proxyserver.
Relaterade ämnen
-
Single-Threaded och för flertrådad kommunikation