Sdílet prostřednictvím


Inicializace instancí

Inicializační ukázka rozšiřuje ukázku sdružování tím, že definuje rozhraní, IObjectControl, které umožňuje upravit inicializaci objektu prostřednictvím jeho aktivace a deaktivace. Klient vyvolá metody, které vracejí objekt do zásobníku a které objekt do zásobníku nevracejí.

Poznámka:

Postup nastavení a pokyny k sestavení pro tuto ukázku najdete na konci tohoto tématu.

Body rozšiřitelnosti

Prvním krokem při vytváření rozšíření WCF (Windows Communication Foundation) je rozhodnutí o bodu rozšiřitelnosti, který se má použít. Ve WCF termín EndpointDispatcher odkazuje na komponentu modulu runtime zodpovědnou za převod příchozích zpráv na volání metod ve službě uživatele a k převodu vrácených hodnot z této metody na odchozí zprávu. Služba WCF vytvoří Dispatcher koncového bodu pro každý koncový bod.

EndpointDispatcher nabízí rozšiřitelnost rozsahu koncového bodu pro všechny zprávy přijaté nebo odeslané službou pomocí třídy EndpointDispatcher. Tato třída umožňuje přizpůsobit různé vlastnosti, které řídí chování EndpointDispatcher. Tato ukázka se zaměřuje na InstanceProvider vlastnost, která odkazuje na objekt, který poskytuje instance třídy služby.

IInstanceProvider

Ve wcf EndpointDispatcher vytváří instance třídy služby pomocí zprostředkovatele instance, který implementuje IInstanceProvider rozhraní. Toto rozhraní má pouze dvě metody:

Fond objektů

Třída ObjectPoolInstanceProvider obsahuje implementaci fondu objektů. Tato třída implementuje IInstanceProvider rozhraní pro interakci s vrstvou modelu služby. Když EndpointDispatcher volá metodu GetInstance místo vytvoření nové instance, vlastní implementace hledá existující objekt ve fondu v paměti. Pokud je k dispozici, vrátí se. V opačném případě zkontroluje, ObjectPoolInstanceProvider zda ActiveObjectsCount vlastnost (počet objektů vrácených z fondu) dosáhla maximální velikosti fondu. Pokud ne, vytvoří se nová instance, která se vrátí volajícímu, a poté se ActiveObjectsCount zvýší. V opačném případě se požadavek na vytvoření objektu zařadí do fronty na stanovenou dobu. Implementace GetObjectFromThePool je prezentována v následující ukázce kódu.

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"));
}

Uživatelská ReleaseInstance implementace přidá uvolněnou instanci zpět do fondu a dekrementuje ActiveObjectsCount veličinu. EndpointDispatcher může volat tyto metody z různých vláken, a proto je vyžadován synchronizovaný přístup k členům úrovně třídy ve ObjectPoolInstanceProvider třídě.

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);
}

Metoda ReleaseInstance poskytuje funkci inicializace vyčištění. Fond obvykle udržuje minimální počet objektů po dobu životnosti fondu. Může však existovat období nadměrného využití, která vyžadují vytvoření dalších objektů ve fondu, aby dosáhla maximálního limitu zadaného v konfiguraci. Když se fond stane méně aktivní, tyto přebytečné objekty mohou představovat další zátěž. Pokud tedy activeObjectsCount dosáhne nuly, spustí se časovač nečinnosti, který aktivuje a provede cyklus čištění.

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

Rozšíření vrstvy ServiceModel jsou napojena pomocí následujících chování:

  • Chování služby: To umožňuje přizpůsobení celého běhu služby.

  • Funkce chování koncových bodů: Ty umožňují přizpůsobení konkrétního koncového bodu služby, včetně prvku EndpointDispatcher.

  • Chování kontraktů: To umožňuje přizpůsobení tříd ClientRuntime nebo DispatchRuntime na klientovi a službě.

  • Chování operací: To umožňuje přizpůsobení buď ClientOperation nebo DispatchOperation tříd v klientovi nebo službě.

Pro účely rozšíření sdružování objektů je možné vytvořit chování koncového bodu nebo chování služby. V tomto příkladu používáme chování služby, které používá schopnost sdružování objektů na každý koncový bod služby. Chování služby se vytváří implementací IServiceBehavior rozhraní. Existuje několik způsobů, jak informovat ServiceModel o vlastních chováních:

  • Použití vlastního atributu

  • Imperativním přidáním do kolekce chování popisu služby.

  • Rozšíření konfiguračního souboru

Tato ukázka používá vlastní atribut. Při vytváření ServiceHost prozkoumává atributy použité v definici typu služby a přidává dostupné chování do kolekce chování popisu služby.

Rozhraní IServiceBehavior má tři metody: Validate,AddBindingParameters, a .ApplyDispatchBehavior Když je ServiceHost inicializováno, WCF volá tyto metody. IServiceBehavior.Validate je volána jako první; umožňuje službě kontrolovat nekonzistence. IServiceBehavior.AddBindingParameters je zavolána jako další; tato metoda je potřebná pouze ve velmi pokročilých scénářích. IServiceBehavior.ApplyDispatchBehavior je volána jako poslední a zodpovídá za konfiguraci modulu runtime. Následující parametry se předávají do IServiceBehavior.ApplyDispatchBehavior:

  • Description: Tento parametr poskytuje popis služby pro celou službu. Můžete ho použít ke kontrole popisových dat o koncových bodech, kontraktech, vazbách a dalších datech přidružených ke službě.

  • ServiceHostBase: Tento parametr poskytuje ServiceHostBase, který je aktuálně inicializován.

Ve vlastní IServiceBehavior implementaci je nová instance ObjectPoolInstanceProvider vytvořena a přiřazena k vlastnosti InstanceProvider v každém EndpointDispatcher, který je připojen k ServiceHostBase.

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;
                 }
             }
         }
     }
}

Kromě IServiceBehavior implementace ObjectPoolingAttribute třída má několik členů pro přizpůsobení fondu objektů pomocí argumentů atributu. Mezi tyto členy patří MaxSize, MinSizeEnableda CreationTimeout, aby odpovídaly sadě funkcí sdružování objektů poskytované službami .NET Enterprise Services.

Chování při sdružování objektů je teď možné přidat do služby WCF přidáním poznámek k implementaci služby pomocí nově vytvořeného vlastního ObjectPooling atributu.

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

Aktivace a deaktivace připojení

Primárním cílem sdružování objektů je optimalizovat krátkodobé objekty s relativně nákladným vytvořením a inicializací. Proto může aplikaci v případě správného použití výrazně zvýšit výkon. Vzhledem k tomu, že objekt je vrácen z poolu, je konstruktor volán pouze jednou. Některé aplikace však vyžadují určitou úroveň řízení, aby mohly inicializovat a vyčistit prostředky použité během jednoho kontextu. Například objekt, který se používá pro sadu výpočtů, může před zpracováním dalšího výpočtu resetovat svá soukromá pole. Podnikové služby povolily tento druh inicializace specifické pro konkrétní kontext tím, že umožňují vývojáři objektu přepsat Activate a Deactivate metody ze ServicedComponent základní třídy.

Fond objektů volá metodu Activate těsně před vrácením objektu z fondu. Deactivate je volána, když se objekt vrátí do fondu. Základní ServicedComponent třída má boolean také vlastnost s názvem CanBePooled, která lze použít k upozorňovat fondu, zda lze objekt dále fondovat.

Pro napodobení této funkce ukázka deklaruje veřejné rozhraní (IObjectControl), které má výše uvedené členy. Toto rozhraní je pak implementováno třídami služeb určenými k poskytnutí kontextové inicializace. Implementace musí být upravena IInstanceProvider tak, aby splňovala tyto požadavky. Nyní, když získáte objekt voláním metody GetInstance, musíte zkontrolovat, zda objekt implementuje IObjectControl.. Pokud ano, musíte odpovídajícím způsobem volat metodu Activate.

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

Při vracení objektu do fondu je nutné zkontrolovat vlastnost CanBePooled před jeho opětovným přidáním.

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

Vzhledem k tomu, že vývojář služby může rozhodnout, zda může být objekt sdružen, může počet objektů ve fondu v daném okamžiku klesnout pod minimální velikost. Proto je nutné zkontrolovat, zda počet objektů byl nižší než minimální úroveň, a provést nezbytné inicializace v postupu vyčištění.

// 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());
  }
}

Při spuštění ukázky se požadavky na operace a odpovědi zobrazí v oknech služby i konzoly klienta. Stisknutím klávesy Enter v každém okně konzoly vypnete službu a klienta.

Nastavte, sestavte a spusťte ukázku

  1. Ujistěte se, že jste pro ukázky windows Communication Foundation provedli jednorázovou instalační proceduru.

  2. Pokud chcete sestavit řešení, postupujte podle pokynů v části Ukázky sestavení služby Windows Communication Foundation.

  3. Pokud chcete spustit ukázku v jedno- nebo vícepočítačové konfiguraci, postupujte podle pokynů v Spuštění ukázek Windows Communication Foundation.