Megosztás:


Inicializálás inicializálása

Az inicializálási minta egy interfész definiálásával kibővíti a készletezési mintát, IObjectControlamely aktiválással és inaktiválással testre szabja egy objektum inicializálását. Az ügyfél olyan metódusokat hív meg, amelyek visszaadják az objektumot a készletnek, és amelyek nem a készletnek adják vissza az objektumot.

Feljegyzés

A minta telepítési eljárása és összeállítási utasításai a témakör végén találhatók.

Bővíthetőségi pontok

A Windows Communication Foundation (WCF) bővítmény létrehozásának első lépése a használni kívánt bővíthetőségi pont kiválasztása. A WCF-ben az EndpointDispatcher kifejezés egy futtatókörnyezeti összetevőre utal, amely felelős a bejövő üzenetek metódushívásokká alakításáért a felhasználó szolgáltatásában, valamint a visszatérési értékeknek a metódusból kimenő üzenetté alakításáért. A WCF-szolgáltatás minden végponthoz létrehoz egy EndpointDispatchert.

Az EndpointDispatcher a végpont hatókörét (a szolgáltatás által fogadott vagy küldött összes üzenethez) bővíti az EndpointDispatcher osztály használatával. Ez az osztály lehetővé teszi az EndpointDispatcher viselkedését vezérlő különböző tulajdonságok testreszabását. Ez a minta a InstanceProvider szolgáltatásosztály példányait biztosító objektumra mutató tulajdonságra összpontosít.

IInstanceProvider

A WCF-ben az EndpointDispatcher egy szolgáltatásosztály példányait hozza létre egy olyan példányszolgáltató használatával, amely implementálja az interfészt IInstanceProvider . Ennek a felületnek csak két módszere van:

  • GetInstance: Amikor egy üzenet megérkezik, a diszpécser meghívja a metódust, GetInstance hogy hozzon létre egy példányt a szolgáltatásosztályból az üzenet feldolgozásához. A metódus hívásainak gyakoriságát a InstanceContextMode tulajdonság határozza meg. Ha például a InstanceContextMode tulajdonság értéke be van állítva InstanceContextMode.PerCall, a rendszer létrehoz egy új szolgáltatásosztály-példányt az egyes érkező üzenetek feldolgozásához, így GetInstance az üzenet érkezésekor is ezt nevezzük.

  • ReleaseInstance: Amikor a szolgáltatáspéldány befejezi az üzenet feldolgozását, az EndpointDispatcher meghívja a metódust ReleaseInstance . A metódushoz GetInstance hasonlóan a metódus hívásainak gyakoriságát a InstanceContextMode tulajdonság határozza meg.

Az objektumkészlet

Az ObjectPoolInstanceProvider osztály tartalmazza az objektumkészlet implementációját. Ez az osztály implementálja az interfészt a IInstanceProvider szolgáltatásmodell-réteggel való interakcióhoz. Amikor az EndpointDispatcher meghívja a GetInstance metódust, ahelyett, hogy új példányt hoz létre, az egyéni implementáció egy meglévő objektumot keres egy memórián belüli készletben. Ha elérhető, a függvény visszaadja. Ellenkező esetben ellenőrizze, ObjectPoolInstanceProvider hogy a tulajdonság (a ActiveObjectsCount készletből visszaadott objektumok száma) elérte-e a készlet maximális méretét. Ha nem, a rendszer létrehoz egy új példányt, és visszaadja a hívónak, és ActiveObjectsCount ezt követően megnövekedik. Ellenkező esetben az objektumlétrehozási kérések egy konfigurált időszakra lesznek várólistára állítva. A megvalósítás a GetObjectFromThePool következő mintakódban látható.

private object GetObjectFromThePool()
{
    bool didNotTimeout =
       availableCount.WaitOne(creationTimeout, true);
    if(didNotTimeout)
    {
         object obj = null;
         lock (poolLock)
        {
             if (pool.Count != 0)
             {
                   obj = pool.Pop();
                   activeObjectsCount++;
             }
             else if (pool.Count == 0)
             {
                   if (activeObjectsCount < maxPoolSize)
                   {
                        obj = CreateNewPoolObject();
                        activeObjectsCount++;

                        #if (DEBUG)
                        WritePoolMessage(
                             ResourceHelper.GetString("MsgNewObject"));
                       #endif
                   }
            }
           idleTimer.Stop();
      }
     // Call the Activate method if possible.
    if (obj is IObjectControl)
   {
         ((IObjectControl)obj).Activate();
   }
   return obj;
}
throw new TimeoutException(
ResourceHelper.GetString("ExObjectCreationTimeout"));
}

Az egyéni ReleaseInstance implementáció hozzáadja a felszabadított példányt a készlethez, és lecsökkenti az ActiveObjectsCount értéket. Az EndpointDispatcher különböző szálakból hívhatja meg ezeket a metódusokat, ezért szinkronizált hozzáférésre van szükség az ObjectPoolInstanceProvider osztály osztályszintű tagjaihoz.

public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
    lock (poolLock)
    {
        // Check whether the object can be pooled.
        // Call the Deactivate method if possible.
        if (instance is IObjectControl)
        {
            IObjectControl objectControl = (IObjectControl)instance;
            objectControl.Deactivate();

            if (objectControl.CanBePooled)
            {
                pool.Push(instance);

                #if(DEBUG)
                WritePoolMessage(
                    ResourceHelper.GetString("MsgObjectPooled"));
                #endif
            }
            else
            {
                #if(DEBUG)
                WritePoolMessage(
                    ResourceHelper.GetString("MsgObjectWasNotPooled"));
                #endif
            }
        }
        else
        {
            pool.Push(instance);

            #if(DEBUG)
            WritePoolMessage(
                ResourceHelper.GetString("MsgObjectPooled"));
            #endif
        }

        activeObjectsCount--;

        if (activeObjectsCount == 0)
        {
            idleTimer.Start();
        }
    }

    availableCount.Release(1);
}

A ReleaseInstance metódus egy tisztítási inicializálási funkciót biztosít. A készlet általában minimális számú objektumot tart fenn a készlet élettartamára vonatkozóan. Előfordulhat azonban, hogy a túlzott használat miatt további objektumokat kell létrehozni a készletben, hogy elérjék a konfigurációban megadott maximális korlátot. Végül, amikor a készlet kevésbé aktív lesz, ezek a felesleges objektumok többletterhelést jelenthetnek. Ezért amikor a activeObjectsCount nullát eléri, elindul egy tétlen időzítő, amely elindítja és elvégzi a tisztítási ciklust.

if (activeObjectsCount == 0)
{
    idleTimer.Start();
}

A ServiceModel-rétegbővítmények a következő viselkedéssel vannak összekapcsolva:

  • Szolgáltatás viselkedése: Ezek lehetővé teszik a teljes szolgáltatás-futtatókörnyezet testreszabását.

  • Végponti viselkedések: Ezek lehetővé teszik egy adott szolgáltatásvégpont testreszabását, beleértve az EndpointDispatchert is.

  • Szerződési viselkedések: Ezek lehetővé teszik az ügyfél vagy ClientRuntime a szolgáltatás vagy osztályok testreszabásátDispatchRuntime.

  • Műveleti viselkedések: Ezek lehetővé teszik az ügyfél vagy ClientOperation a szolgáltatás vagy az osztályok testreszabásátDispatchOperation.

Objektumkészletezési bővítmény céljából végponti vagy szolgáltatásviselkedés hozható létre. Ebben a példában egy szolgáltatás viselkedését használjuk, amely a szolgáltatás minden végpontjára alkalmazza az objektumkészletezési képességet. A szolgáltatás viselkedése a IServiceBehavior felület implementálásával jön létre. A ServiceModel többféleképpen is tudatható az egyéni viselkedésekkel:

  • Egyéni attribútum használata.

  • Feltétlenül adja hozzá a szolgáltatásleírás viselkedésgyűjteményéhez.

  • A konfigurációs fájl kiterjesztése.

Ez a minta egy egyéni attribútumot használ. A ServiceHost létrehozásakor megvizsgálja a szolgáltatás típusdefiníciójában használt attribútumokat, és hozzáadja az elérhető viselkedéseket a szolgáltatásleírás viselkedésgyűjteményéhez.

Az IServiceBehavior interfésznek három módszere van: Validate,AddBindingParameters, és.ApplyDispatchBehavior Ezeket a metódusokat a WCF hívja meg az ServiceHost inicializáláskor. IServiceBehavior.Validate az első; lehetővé teszi a szolgáltatás számára az inkonzisztenciák vizsgálatát. IServiceBehavior.AddBindingParameters a következőnek hívják; ez a módszer csak nagyon speciális helyzetekben szükséges. IServiceBehavior.ApplyDispatchBehavior az utolsó hívás, és felelős a futtatókörnyezet konfigurálásáért. A rendszer a következő paramétereket adja át IServiceBehavior.ApplyDispatchBehavior:

  • Description: Ez a paraméter a teljes szolgáltatás szolgáltatásleírását tartalmazza. Ez a szolgáltatás végpontjaival, szerződéseivel, kötéseivel és a szolgáltatáshoz társított egyéb adatok leírási adatainak vizsgálatára használható.

  • ServiceHostBase: Ez a paraméter az ServiceHostBase inicializálás alatt álló paramétert adja meg.

Az egyéni IServiceBehavior implementációban a rendszer létrehoz egy új példányt ObjectPoolInstanceProvider , amely a InstanceProvider tulajdonsághoz EndpointDispatcher van ServiceHostBaserendelve.

public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
    if (enabled)
    {
        // Create an instance of the ObjectPoolInstanceProvider.
        instanceProvider = new ObjectPoolInstanceProvider(description.ServiceType,
        maxPoolSize, minPoolSize, creationTimeout);

        // Assign our instance provider to Dispatch behavior in each
        // endpoint.
        foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
        {
             ChannelDispatcher cd = cdb as ChannelDispatcher;
             if (cd != null)
             {
                 foreach (EndpointDispatcher ed in cd.Endpoints)
                 {
                        ed.DispatchRuntime.InstanceProvider = instanceProvider;
                 }
             }
         }
     }
}

A megvalósítás mellett IServiceBehavior az ObjectPoolingAttribute osztály több taggal is rendelkezik az objektumkészlet testreszabásához az attribútumargumentumok használatával. Ezek a tagok a .NET Enterprise Services által biztosított objektumkészletezési funkciókészletnek megfelelőt tartalmazzák MaxSizeMinSizeEnabledCreationTimeout.

Az objektumkészletezési viselkedés mostantól hozzáadható egy WCF-szolgáltatáshoz a szolgáltatás implementációjának megjegyzésével az újonnan létrehozott egyéni ObjectPooling attribútummal.

[ObjectPooling(MaxSize=1024, MinSize=10, CreationTimeout=30000]
public class PoolService : IPoolService
{
  // …
}

Aktiválás és inaktiválás csatlakoztatása

Az objektumkészletezés elsődleges célja a rövid élettartamú objektumok viszonylag költséges létrehozása és inicializálása. Ezért jelentősen növelheti az alkalmazás teljesítményét, ha megfelelően használják. Mivel az objektumot a rendszer a készletből adja vissza, a konstruktor csak egyszer lesz meghívva. Egyes alkalmazások azonban bizonyos szintű vezérlést igényelnek, hogy inicializálhassák és megtisztíthassák az egyetlen környezetben használt erőforrásokat. A számításokhoz használt objektumok például alaphelyzetbe állíthatják a privát mezőket a következő számítás feldolgozása előtt. Az Enterprise Services ezt a környezetspecifikus inicializálást úgy engedélyezte, hogy az objektumfejlesztő felülbírálja Activate a Deactivate metódusokat az ServicedComponent alaposztályból.

Az objektumkészlet meghívja a metódust Activate , mielőtt visszaadja az objektumot a készletből. Deactivate akkor lesz meghívva, amikor az objektum visszakerül a készletbe. Az ServicedComponent alaposztálynak van egy boolean nevű tulajdonsága CanBePooledis, amellyel értesítheti a készletet, hogy az objektum tovább készletezhető-e.

A funkció utánzásához a minta egy nyilvános felületet (IObjectControl) deklarál, amely rendelkezik a fent említett tagokkal. Ezt a felületet ezután a szolgáltatásosztályok implementálják, amelyek környezetspecifikus inicializálást biztosítanak. A IInstanceProvider megvalósítást módosítani kell, hogy megfeleljen ezeknek a követelményeknek. Most, minden alkalommal, amikor egy objektumot kap a GetInstance metódus meghívásával, ellenőriznie kell, hogy az objektum megvalósítja-e IObjectControl. , ha igen, megfelelően kell meghívnia a Activate metódust.

if (obj is IObjectControl)
{
    ((IObjectControl)obj).Activate();
}

Amikor egy objektumot ad vissza a készlethez, ellenőrizni kell a CanBePooled tulajdonságot, mielőtt hozzáadja az objektumot a készlethez.

if (instance is IObjectControl)
{
    IObjectControl objectControl = (IObjectControl)instance;
    objectControl.Deactivate();
    if (objectControl.CanBePooled)
    {
       pool.Push(instance);
    }
}

Mivel a szolgáltatásfejlesztő eldöntheti, hogy egy objektum készletezhető-e, a készletben lévő objektumok száma egy adott időpontban a minimális méret alá csökkenhet. Ezért ellenőriznie kell, hogy az objektumszám a minimális szint alá csökkent-e, és a tisztítási eljárás során végre kell hajtania a szükséges inicializálást.

// Remove the surplus objects.
if (pool.Count > minPoolSize)
{
  // Clean the surplus objects.
}
else if (pool.Count < minPoolSize)
{
  // Reinitialize the missing objects.
  while(pool.Count != minPoolSize)
  {
    pool.Push(CreateNewPoolObject());
  }
}

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 minta beállítása, összeállítása és futtatása

  1. Győződjön meg arról, hogy elvégezte a Windows Communication Foundation-minták egyszeri beállítási eljárását.

  2. A megoldás létrehozásához kövesse a Windows Communication Foundation-minták készítésére vonatkozó utasításokat.

  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ásával kapcsolatos utasításokat.