Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
Az élettartam-minta bemutatja, hogyan írhat windowsos kommunikációs alap (WCF) bővítményt, hogy egyéni élettartam-szolgáltatásokat biztosítson a megosztott WCF-szolgáltatáspéldányokhoz.
Megjegyzés:
A minta telepítési eljárása és összeállítási utasításai a cikk végén találhatók.
Megosztott példányosítás
A WCF számos instancing módot kínál a szolgáltatáspéldányokhoz. A cikkben tárgyalt megosztott instancing mód lehetővé teszi egy szolgáltatáspéldány több csatorna közötti megosztását. Az ügyfelek kapcsolatba léphetnek a szolgáltatás egy gyári metódusával, és új csatornát hozhatnak létre a kommunikáció elindításához. Az alábbi kódrészlet bemutatja, hogy egy ügyfélalkalmazás hogyan hoz létre új csatornát egy meglévő szolgáltatáspéldányhoz:
// Create a header for the shared instance id
MessageHeader shareableInstanceContextHeader = MessageHeader.CreateHeader(
CustomHeader.HeaderName,
CustomHeader.HeaderNamespace,
Guid.NewGuid().ToString());
// Create the channel factory
ChannelFactory<IEchoService> channelFactory =
new ChannelFactory<IEchoService>("echoservice");
// Create the first channel
IEchoService proxy = channelFactory.CreateChannel();
// Call an operation to create shared service instance
using (new OperationContextScope((IClientChannel)proxy))
{
OperationContext.Current.OutgoingMessageHeaders.Add(shareableInstanceContextHeader);
Console.WriteLine("Service returned: " + proxy.Echo("Apple"));
}
((IChannel)proxy).Close();
// Create the second channel
IEchoService proxy2 = channelFactory.CreateChannel();
// Call an operation using the same header that will reuse the shared service instance
using (new OperationContextScope((IClientChannel)proxy2))
{
OperationContext.Current.OutgoingMessageHeaders.Add(shareableInstanceContextHeader);
Console.WriteLine("Service returned: " + proxy2.Echo("Apple"));
}
A többi instancing módtól eltérően a megosztott instancing mód egyedi módon teszi közzé a szolgáltatáspéldányokat. Alapértelmezés szerint, amikor az összes csatorna zárva van egy InstanceContext számára, a WCF szolgáltatás futtatókörnyezete ellenőrzi, hogy a szolgáltatást InstanceContextMode konfigurálták-e PerCall vagy PerSession-ra, és ha igen, kiadja a példányt, és felszabadítja az erőforrásokat. Egyéni IInstanceContextProvider használat esetén a WCF meghívja a IsIdle szolgáltató implementálásának metódusát a példány kiadása előtt. Ha IsIdle visszaadja true, az azt jelenti, hogy a példány felszabadításra kerül. Máskülönben az IInstanceContextProvider implementáció felelős azért, hogy visszahívási módszerrel értesítse az Dispatcher-t az inaktív állapotról. Ez a NotifyIdle metódus meghívásával történik a szolgáltatónál.
Ez a minta bemutatja, hogyan késleltetheti a InstanceContext kiadását tétlenségi időtúllépéssel, ami 20 másodperc.
Az InstanceContext kiterjesztése
A WCF-ben InstanceContext a kapcsolat a szolgáltatáspéldány és a Dispatcher között. A WCF lehetővé teszi, hogy bővítse ezt a futtatókörnyezeti összetevőt úgy, hogy új állapotot vagy viselkedést ad hozzá a bővíthető objektumminta használatával. Az bővíthető objektumminta a WCF-ben a meglévő futtatókörnyezeti osztályok új funkciókkal való kiterjesztésére vagy új állapotfunkciók objektumhoz való hozzáadására szolgál. A bővíthető objektummintában három interfész található: IExtensibleObject<T>, IExtension<T>és IExtensionCollection<T>.
Az IExtensibleObject<T> interfészt objektumok implementálják, hogy lehetővé tegyék a funkciók testreszabását lehetővé tevő bővítményeket.
Az IExtension<T> interfészt olyan objektumok implementálják, amelyek típusosztályok Tbővítményei lehetnek.
Végül pedig a IExtensionCollection<T> felület az IExtension<T> implementációk olyan gyűjteménye, amely lehetővé teszi egy IExtension<T> típus szerinti implementáció lekérését.
Ezért a InstanceContext kibővítéséhez implementálnia kell a IExtension<T> interfészt. Ebben a mintaprojektben az osztály tartalmazza ezt a CustomLeaseExtension megvalósítást.
class CustomLeaseExtension : IExtension<InstanceContext>
{
}
Az IExtension<T> interfész két metódust Attach és Detach. Mivel a nevük azt jelenti, hogy ez a két metódus akkor lesz meghívva, amikor a futtatókörnyezet csatolja és leválasztja a bővítményt az InstanceContext osztály egy példányára. Ebben a mintában a Attach metódus szolgál a InstanceContext objektum nyomon követésére, amely a bővítmény aktuális példányához tartozik.
InstanceContext owner;
public void Attach(InstanceContext owner)
{
this.owner = owner;
}
Emellett hozzá kell adnia a bővítményhez szükséges implementációt a kiterjesztett élettartam támogatásához. Ezért az interfész a ICustomLease kívánt módszerekkel deklarálva van, és az CustomLeaseExtension osztályban van implementálva.
interface ICustomLease
{
bool IsIdle { get; }
InstanceContextIdleCallback Callback { get; set; }
}
class CustomLeaseExtension : IExtension<InstanceContext>, ICustomLease
{
}
Amikor a WCF meghívja a IsIdle metódust a IInstanceContextProvider megvalósítás során, a rendszer átirányítja ezt a hívást a IsIdleCustomLeaseExtension metódushoz. Ezután a CustomLeaseExtension ellenőrzi a saját állapotát, hogy az InstanceContext üresjáratban van-e. Ha tétlen, akkor ad vissza true. Ellenkező esetben egy időzítőt indít el egy meghatározott mennyiségű hosszabb élettartamra.
public bool IsIdle
{
get
{
lock (thisLock)
{
if (isIdle)
{
return true;
}
else
{
StartTimer();
return false;
}
}
}
}
Az időzítő Elapsed eseményében a visszahívási függvényt a Diszpécser hívja meg, hogy elindítson egy újabb tisztítási ciklust.
void idleTimer_Elapsed(object sender, ElapsedEventArgs args)
{
lock (thisLock)
{
StopTimer();
isIdle = true;
Utility.WriteMessageToConsole(
ResourceHelper.GetString("MsgLeaseExpired"));
callback(owner);
}
}
Nem lehet megújítani a futó időzítőt, ha új üzenet érkezik az üresjárati állapotba áthelyezett példányhoz.
A minta implementálja a IInstanceContextProvider -t, hogy elfogja a IsIdle metódus hívásait és átirányítsa őket a CustomLeaseExtension-re. A IInstanceContextProvider megvalósítás az osztályban CustomLifetimeLease található. A IsIdle metódus akkor lesz meghívva, ha a WCF a szolgáltatáspéldány kiadására készül. A ServiceBehavior ISharedSessionInstance gyűjteményében azonban egy adott IInstanceContextProvider implementációnak csak egy példánya található meg. Ez azt jelenti, hogy nem lehet tudni, hogy a InstanceContext be van-e zárva abban az időpontban, amikor a WCF ellenőrzi a IsIdle metódust. Ezért ez a minta szálzárolással szerializálja a kéréseket a IsIdle metódushoz.
Fontos
A szálzárolás használata nem ajánlott, mert a szerializálás súlyosan befolyásolhatja az alkalmazás teljesítményét.
Az osztály egy privát tagmezőt használ az CustomLifetimeLease inaktív állapot nyomon követéséhez, és a IsIdle metódus adja vissza. Minden alkalommal, amikor meghívja a IsIdle metódust, a rendszer visszaadja a isIdle mezőt, és visszaállítja a következőre false: . Fontos, hogy ezt az értéket false állítsa be annak érdekében, hogy a diszpécser meghívja a metódust NotifyIdle.
public bool IsIdle(InstanceContext instanceContext)
{
get
{
lock (thisLock)
{
//...
bool idleCopy = isIdle;
isIdle = false;
return idleCopy;
}
}
}
Ha a IInstanceContextProvider.IsIdle metódus visszatér false, a Diszpécser a NotifyIdle metódus használatával regisztrál egy visszahívási függvényt. Ez a módszer a felszabadításra kerülő InstanceContext hivatkozást kapja meg. Ezért a mintakód lekérdezheti a ICustomLease típusbővítményt, és kiterjesztett állapotban ellenőrizheti a ICustomLease.IsIdle tulajdonságot.
public void NotifyIdle(InstanceContextIdleCallback callback,
InstanceContext instanceContext)
{
lock (thisLock)
{
ICustomLease customLease =
instanceContext.Extensions.Find<ICustomLease>();
customLease.Callback = callback;
isIdle = customLease.IsIdle;
if (isIdle)
{
callback(instanceContext);
}
}
}
ICustomLease.IsIdle A tulajdonság ellenőrzése előtt be kell állítani a Visszahívás tulajdonságot, mivel ez elengedhetetlen CustomLeaseExtension ahhoz, hogy értesítse a kézbesítőt, amikor tétlenné válik. Ha ICustomLease.IsIdle visszaadja true, a isIdle privát tag egyszerűen be CustomLifetimeLease van állítva, true és meghívja a visszahívási módszert. Mivel a kód zárolást tartalmaz, más szálak nem módosíthatják ennek a privát tagnak az értékét. Következő alkalommal, amikor a Dispatcher meghívja a IInstanceContextProvider.IsIdle példányt, visszatér a true értékkel, és lehetővé teszi a Dispatcher számára a példány kiadását.
Most, hogy befejeződött az egyéni bővítmény alapműve, hozzá kell csatlakoztatni a szolgáltatásmodellhez. Az CustomLeaseExtension implementáció és a InstanceContext összekapcsolásához a WCF biztosítja a IInstanceContextInitializer interfészt a InstanceContext inicializálásának végrehajtására. A mintában az CustomLeaseInitializer osztály implementálja ezt az interfészt, és hozzáad egy CustomLeaseExtension példányt az Extensions gyűjteményhez az egyetlen inicializáló metódusból. A Dispatcher a InstanceContext inicializálása közben hívja ezt a metódust.
public void InitializeInstanceContext(InstanceContext instanceContext,
System.ServiceModel.Channels.Message message, IContextChannel channel)
//...
IExtension<InstanceContext> customLeaseExtension =
new CustomLeaseExtension(timeout, headerId);
instanceContext.Extensions.Add(customLeaseExtension);
}
Végül az IInstanceContextProvider implementáció az IServiceBehavior implementáció használatával csatlakozik a szolgáltatásmodellhez. Ez az implementáció az CustomLeaseTimeAttribute osztályba kerül, és az alaposztályból is származik, hogy ezt a Attribute viselkedést attribútumként tegye elérhetővé.
public void ApplyDispatchBehavior(ServiceDescription description,
ServiceHostBase serviceHostBase)
{
CustomLifetimeLease customLease = new CustomLifetimeLease(timeout);
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceContextProvider = customLease;
}
}
}
}
Ez a viselkedés hozzáadható egy mintaszolgáltatás-osztályhoz, ha azt a CustomLeaseTime attribútummal látjuk el.
[CustomLeaseTime(Timeout = 20000)]
public class EchoService : IEchoService
{
//…
}
A minta futtatásakor a műveleti kérelmek és a válaszok megjelennek a szolgáltatás és az ügyfélkonzol ablakaiban is. A szolgáltatás és az ügyfél leállításához nyomja le az ENTER billentyűt az egyes konzolablakokban.
A példa beállítása, elkészítése és futtatása
Győződjön meg arról, hogy elvégezte a Windows Communication Foundation-mintákOne-Time beállítási eljárását.
A megoldás C# vagy Visual Basic .NET kiadásának létrehozásához kövesse Windows Communication Foundation-mintákcímű témakör utasításait.
Ha a mintát egy vagy több gép közötti konfigurációban szeretné futtatni, kövesse A Windows Communication Foundation-minták futtatásacímű témakör utasításait.