Sdílet prostřednictvím


Vlastní životnost

Ukázka životnosti ukazuje, jak napsat rozšíření WCF (Windows Communication Foundation), které poskytuje vlastní služby životnosti pro sdílené instance služby WCF.

Poznámka:

Postup nastavení a pokyny k sestavení pro tuto ukázku najdete na konci tohoto článku.

Sdílené instancování

WCF nabízí několik režimů vytváření instancí pro instance služby. Sdílený režim vytváření instancí popsaný v tomto článku poskytuje způsob sdílení instance služby mezi více kanály. Klienti mohou kontaktovat tovární metodu ve službě a vytvořit nový kanál pro zahájení komunikace. Následující fragment kódu ukazuje, jak klientská aplikace vytvoří nový kanál pro existující instanci služby:

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

Na rozdíl od jiných režimů má sdílený režim instancování jedinečný způsob uvolňování instancí služby. Ve výchozím nastavení, když jsou všechny kanály uzavřeny pro InstanceContext, modul runtime služby WCF zkontroluje, zda je služba InstanceContextMode nakonfigurována na PerCall nebo PerSession, a pokud ano, uvolní instanci a deklaruje prostředky. Pokud se používá vlastní IInstanceContextProvider, WCF vyvolá metodu IsIdle implementace poskytovatele před vydáním instance. Pokud IsIdle vrátí true, instance je uvolněna, v opačném případě je IInstanceContextProvider implementace zodpovědná za oznámení Dispatcher o stavu nečinnosti pomocí metody zpětného volání. To se provádí voláním NotifyIdle metody zprostředkovatele.

Tato ukázka ukazuje, jak můžete zpozdit uvolnění InstanceContext s časovým limitem nečinnosti 20 sekund.

Rozšíření instanceContext

Ve WCF je InstanceContext propojení mezi instancí služby a Dispatcher. WCF umožňuje rozšířit tuto komponentu modulu runtime přidáním nového stavu nebo chování pomocí jeho rozšiřitelného vzoru objektu. Rozšiřitelný vzor objektu se používá ve WCF k rozšíření existujících tříd modulu runtime s novými funkcemi nebo k přidání nových stavových funkcí do objektu. V rozšiřitelném objektovém vzoru existují tři rozhraní: IExtensibleObject<T>, IExtension<T>a IExtensionCollection<T>.

Rozhraní IExtensibleObject<T> je implementováno objekty, které umožňují rozšíření, která přizpůsobí jejich funkce.

Rozhraní IExtension<T> je implementováno objekty, které mohou být rozšíření tříd typu T.

A konečně, IExtensionCollection<T> rozhraní je kolekce IExtension<T> implementací, které umožňují načíst implementaci IExtension<T> podle jejich typu.

Proto, aby bylo možné rozšířit InstanceContext, musíte implementovat IExtension<T> rozhraní. V tomto ukázkovém projektu CustomLeaseExtension třída obsahuje tuto implementaci.

class CustomLeaseExtension : IExtension<InstanceContext>
{
}

Rozhraní IExtension<T> má dvě metody Attach a Detach. Jak jejich názvy naznačují, tyto dvě metody se volají, když modul runtime připojí a odpojí rozšíření k instanci třídy InstanceContext. V této ukázce se metoda Attach používá pro sledování objektu InstanceContext, který patří k aktuální instanci rozšíření.

InstanceContext owner;

public void Attach(InstanceContext owner)
{
    this.owner = owner;
}

Kromě toho musíte do rozšíření přidat potřebnou implementaci, která poskytuje podporu delší životnosti. ICustomLease Proto je rozhraní deklarováno s požadovanými metodami a je implementováno ve CustomLeaseExtension třídě.

interface ICustomLease
{
    bool IsIdle { get; }
    InstanceContextIdleCallback Callback { get; set; }
}

class CustomLeaseExtension : IExtension<InstanceContext>, ICustomLease
{
}

Když WCF vyvolá metodu IsIdle v implementaci IInstanceContextProvider, toto volání je směrováno na metodu IsIdle objektu CustomLeaseExtension. Potom zkontroluje CustomLeaseExtension jeho soukromý stav a zjistí, jestli InstanceContext je nečinný. Pokud je nečinný, vrátí true. V opačném případě se spustí časovač pro zadanou dobu životnosti.

public bool IsIdle
{
  get
  {
    lock (thisLock)
    {
      if (isIdle)
      {
        return true;
      }
      else
      {
        StartTimer();
        return false;
      }
    }
  }
}

V události časovače Elapsed se volá funkce zpětného volání v Dispečeru, aby se spustil další cyklus čištění.

void idleTimer_Elapsed(object sender, ElapsedEventArgs args)
{
    lock (thisLock)
    {
        StopTimer();
        isIdle = true;
        Utility.WriteMessageToConsole(
            ResourceHelper.GetString("MsgLeaseExpired"));
        callback(owner);
    }
}

Neexistuje způsob, jak obnovit časovač spuštění, když přijde nová zpráva pro instanci, která se přesune do stavu nečinnosti.

Ukázka implementuje IInstanceContextProvider k zachycení volání metody IsIdle a jejich směrování na CustomLeaseExtension. Implementace IInstanceContextProvider je obsažena ve CustomLifetimeLease třídě. Metoda IsIdle se vyvolá, když se WCF chystá uvolnit instanci služby. Existuje však pouze jedna instance konkrétní ISharedSessionInstance implementace v kolekci ServiceBehavior IInstanceContextProvider . To znamená, že neexistuje způsob, jak zjistit, jestli InstanceContext je uzavřen v době, kdy WCF kontroluje metodu IsIdle . Proto tato ukázka používá uzamykání vláken k serializaci požadavků na metodu IsIdle .

Důležité

Použití uzamčení vlákna není doporučeným přístupem, protože serializace může vážně ovlivnit výkon vaší aplikace.

Soukromé pole člena se používá v třídě CustomLifetimeLease ke sledování stavu nečinnosti a je vráceno IsIdle metodou. Pokaždé když je volána metoda IsIdle, se pole isIdle vrátí a resetuje na false. Je nezbytné nastavit tuto hodnotu tak false , aby se zajistilo, že Dispatcher volá metodu NotifyIdle .

public bool IsIdle(InstanceContext instanceContext)
{
    get
    {
        lock (thisLock)
        {
            //...
            bool idleCopy = isIdle;
            isIdle = false;
            return idleCopy;
        }
    }
}

Pokud metoda IInstanceContextProvider.IsIdle vrátí false, Dispatcher zaregistruje zpětnou volací funkci pomocí metody NotifyIdle. Tato metoda obdrží odkaz na InstanceContext, které se uvolňuje. Vzorový kód proto může provádět dotazy na ICustomLease rozšíření typu a zkontrolovat ICustomLease.IsIdle vlastnost v rozšířeném stavu.

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

Před kontrolou vlastnosti ICustomLease.IsIdle je třeba nejprve nastavit vlastnost zpětného volání, protože je to nezbytné, aby CustomLeaseExtension mohl oznámit dispečeru, když přejde do nečinnosti. Pokud ICustomLease.IsIdle vrátí true, pak se soukromý člen isIdle jednoduše nastaví v CustomLifetimeLease na true, a poté se zavolá metoda zpětného volání. Protože kód obsahuje zámek, ostatní vlákna nemohou změnit hodnotu tohoto soukromého člena. A při příštím volání IInstanceContextProvider.IsIdleDispatcher vrátí true a umožní Dispatcher uvolnit instanci.

Teď, když je základ rozšíření na míru dokončený, musí být napojen na model služby. Ke propojení CustomLeaseExtension implementace s InstanceContext poskytuje WCF rozhraní IInstanceContextInitializer pro provedení inicializace InstanceContext. V ukázce třída CustomLeaseInitializer implementuje toto rozhraní a přidává instanci CustomLeaseExtension do kolekce Extensions jedinou inicializací metody. Tato metoda je volána Dispatcherem při inicializaci InstanceContext.

public void InitializeInstanceContext(InstanceContext instanceContext,
    System.ServiceModel.Channels.Message message, IContextChannel channel)

    //...

    IExtension<InstanceContext> customLeaseExtension =
        new CustomLeaseExtension(timeout, headerId);
    instanceContext.Extensions.Add(customLeaseExtension);
}

Nakonec se IInstanceContextProvider implementace připojí k modelu služby pomocí IServiceBehavior implementace. Implementace je umístěna ve třídě CustomLeaseTimeAttribute a také odvozená ze základní třídy Attribute k vystavení tohoto chování jako atribut.

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

Toto chování lze přidat do ukázkové třídy služby tak, že ji označíte atributem CustomLeaseTime .

[CustomLeaseTime(Timeout = 20000)]
public class EchoService : IEchoService
{
  //…
}

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.

Jak nastavit, sestavit a spustit ukázku

  1. Ujistěte se, že jste provedli postup nastaveníOne-Time vzorků Windows Communication Foundation.

  2. Pokud chcete sestavit verzi C# nebo Visual Basic .NET řešení, postupujte podle pokynů v Sestavení ukázek Windows Communication Foundation.

  3. Pokud chcete spustit ukázku v konfiguraci pro jeden počítač nebo pro více počítačů, postupujte podle pokynů v Spuštění ukázek Windows Communication Foundation.