Megosztás:


Egyéni élettartam

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

  1. 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.

  2. 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.

  3. 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.