Benutzerdefinierte LebensdauerCustom Lifetime

Dieses Beispiel veranschaulicht, wie so schreiben Sie eine Windows Communication Foundation (WCF)-Erweiterung, um benutzerdefinierte Lebensdauerdienste für freigegebene Instanzen von WCF-Dienst bereitzustellen.This sample demonstrates how to write a Windows Communication Foundation (WCF) extension to provide custom lifetime services for shared WCF service instances.

Hinweis

Die Setupprozedur und die Buildanweisungen für dieses Beispiel befinden sich am Ende dieses Themas.The setup procedure and build instructions for this sample are located at the end of this topic.

Freigegebene InstanziierungShared Instancing

WCF bietet mehrere instanziierungsmodi für Ihre Dienstinstanzen.WCF offers several instancing modes for your service instances. Der freigegebene Instanziierungsmodus, der in diesem Thema behandelt wird, bietet eine Möglichkeit, eine Dienstinstanz zwischen mehreren Kanälen freizugeben.The Shared Instancing mode covered in this topic provides a way to share a service instance between multiple channels. Clients können entweder die Endpunktadresse der Instanz lokal auflösen oder eine Factorymethode im Dienst kontaktieren, um die Endpunktadresse einer ausgeführten Instanz abzurufen.Clients can either resolve the instance’s endpoint address locally or contact a factory method in the service to obtain the endpoint address of a running instance. Sobald die Endpunktadresse vorliegt, kann ein neuer Kanal erstellt und die Kommunikation gestartet werden.Once it has the endpoint address, it can create a new channel and start communication. Im folgenden Codeausschnitt wird gezeigt, wie eine Clientanwendung einen neuen Kanal zu einer vorhandenen Dienstinstanz erstellt.The following code snippet shows how a client application creates a new channel to an existing service instance.

// Create the first channel.  
IEchoService proxy = channelFactory.CreateChannel();  

// Resolve the instance.  
EndpointAddress epa = ((IClientChannel)proxy).ResolveInstance();  

// Create new channel factory with the endpoint address resolved by   
// previous statement.  
ChannelFactory<IEchoService> channelFactory2 =  
                new ChannelFactory<IEchoService>("echoservice",  
                epa);  

// Create the second channel to the same instance.  
IEchoService proxy2 = channelFactory2.CreateChannel();  

Der freigegebene Instanziierungsmodus unterscheidet sich von anderen Instanziierungsmodi in seiner einzigartigen Methode zum Freigeben von Dienstinstanzen.Unlike other instancing modes, the shared instancing mode has a unique way of releasing the service instances. Wenn alle Kanäle für eine Instanz geschlossen sind, wird die WCF-Dienstlaufzeit ein Timer gestartet.When all the channels are closed for an instance, the service WCF runtime starts a timer. Wenn niemand eine Verbindung herstellt, bevor das Timeout abläuft, wird WCF die Instanz frei und die Ressourcen.If nobody makes a connection before the timeout expires, WCF releases the instance and claims the resources. Im Rahmen der beendigungsprozedur ruft WCF die IsIdle -Methode für alle IInstanceContextProvider Implementierungen, bevor die Instanz freigegeben.As a part of the teardown procedure WCF invokes the IsIdle method of all IInstanceContextProvider implementations before releasing the instance. Wenn alle Implementierungen true zurückgeben, wird die Instanz freigegeben.If all of them return true the instance is released. Andernfalls ist die IInstanceContextProvider-Implementierung dafür zuständig, den Dispatcher unter Verwendung einer Rückrufmethode von dem Leerlaufzustand zu benachrichtigen.Otherwise the IInstanceContextProvider implementation is responsible for notifying the Dispatcher of the idle state by using a callback method.

Standardmäßig beträgt der Leerlauftimeoutwert von InstanceContext eine Minute.By default, the idle timeout value of InstanceContext is one minute. In diesem Beispiel wird jedoch gezeigt, wie Sie diesen Wert erweitern können, indem Sie die benutzerdefinierte Erweiterung verwenden.However this sample demonstrates how you can extend this using a custom extension.

Erweitern von InstanceContextExtending the InstanceContext

In WCF InstanceContext ist der Link zwischen der Dienstinstanz und die Dispatcher.In WCF, InstanceContext is the link between the service instance and the Dispatcher. WCF können Sie diese Laufzeitkomponente zu erweitern, indem mithilfe des erweiterbaren Objektmusters Zustand "Neu" oder Verhalten hinzufügen.WCF allows you to extend this runtime component by adding new state or behavior by using its extensible object pattern. Das erweiterbare Objektmuster wird in WCF verwendet, um vorhandene Laufzeitklassen neue Funktionen zu erweitern oder um neue Zustandsfunktionen zu einem Objekt hinzuzufügen.The extensible object pattern is used in WCF to either extend existing runtime classes with new functionality or to add new state features to an object. Es gibt drei Schnittstellen im erweiterbaren Objektmuster: IExtensibleObject<T>, IExtension<T> und IExtensionCollection<T>.There are three interfaces in the extensible object pattern: IExtensibleObject<T>, IExtension<T>, and IExtensionCollection<T>.

Die IExtensibleObject<T>-Schnittstelle wird von Objekten implementiert, um Erweiterungen zuzulassen, die ihre Funktionalität anpassen.The IExtensibleObject<T> interface is implemented by objects to allow extensions which customize their functionality.

Die IExtension<T>-Schnittstelle wird von Objekten implementiert, die Erweiterungen von Klassen des Typs T sein können.The IExtension<T> interface is implemented by objects that can be extensions of classes of type T.

Die IExtensionCollection<T>-Schnittstelle ist eine Auflistung von IExtensions, die das Abrufen von IExtensions nach Typ zulässt.And finally, the IExtensionCollection<T> interface is a collection of IExtensions that allows for retrieving IExtensions by their type.

Aus diesem Grund müssen Sie die InstanceContext-Schnittstelle implementieren, um den IExtension zu erweitern.Therefore in order to extend the InstanceContext you must implement the IExtension interface. In diesem Beispielprojekt enthält die CustomLeaseExtension-Klasse diese Implementierung.In this sample project the CustomLeaseExtension class contains this implementation.

class CustomLeaseExtension : IExtension<InstanceContext>  
{  
}  

Die IExtension-Schnittstelle verfügt über zwei Methoden: Attach und Detach.The IExtension interface has two methods Attach and Detach. Wie ihre Namen vermuten lassen, werden diese beiden Methoden aufgerufen, wenn die Laufzeit die Erweiterung an eine Instanz der InstanceContext-Klasse anfügt oder von der Instanz löst.As their names imply, these two methods are called when the runtime attaches and detaches the extension to an instance of the InstanceContext class. In diesem Beispiel wird die Attach-Methode für die Nachverfolgung des InstanceContext-Objekts verwendet, das zur aktuellen Instanz der Erweiterung gehört.In this sample, the Attach method is used to keep track of the InstanceContext object that belongs to the current instance of the extension.

InstanceContext owner;  

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

Darüber hinaus müssen Sie zur Bereitstellung der erweiterten Lebensdauerunterstützung die erforderliche Implementierung zur Erweiterung hinzufügen.In addition, you must add the necessary implementation to the extension to provide the extended lifetime support. Deswegen wird die ICustomLease-Schnittstelle mit den gewünschten Methoden deklariert und in der CustomLeaseExtension-Klasse implementiert.Therefore the ICustomLease interface is declared with the desired methods and is implemented in the CustomLeaseExtension class.

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

class CustomLeaseExtension : IExtension<InstanceContext>, ICustomLease  
{  
}  

Wenn WCF aufruft der IsIdle Methode in der IInstanceContextProvider Implementierung dieser Aufruf an die IsIdle Methode der CustomLeaseExtension.When WCF invokes the IsIdle method in the IInstanceContextProvider implementation this call is routed to the IsIdle method of the CustomLeaseExtension. Dann überprüft die CustomLeaseExtension den privaten Zustand, um festzustellen, ob sich der InstanceContext im Leerlauf befindet.Then the CustomLeaseExtension checks its private state to see whether the InstanceContext is idle. Wenn er sich in Leerlauf befindet, wird true zurückgegeben.If it is idle it returns true. Andernfalls wird ein Zeitgeber für eine bestimmte erweiterte Lebensdauerperiode gestartet.Otherwise, it starts a timer for a specified amount of extended lifetime.

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

Im Elapsed-Ereignis des Zeitgebers wird die Rückruffunktion im Verteiler aufgerufen, um einen weiteren Bereinigungszyklus zu starten.In the timer’s Elapsed event the callback function in the Dispatcher is called in order to start another clean up cycle.

void idleTimer_Elapsed(object sender, ElapsedEventArgs args)  
{  
    idleTimer.Stop();  
    isIdle = true;    
    callback(owner);  
}  

Der ausgeführte Zeitgeber kann nicht erneuert werden, wenn eine neue Nachricht für die Instanz eingeht, die in den Leerlaufzustand verschoben wird.There is no way to renew the running timer when a new message arrives for the instance being moved to the idle state.

Im Beispiel wird IInstanceContextProvider implementiert, um die Aufrufe der IsIdle-Methode abzufangen und diese zur CustomLeaseExtension weiterzuleiten.The sample implements IInstanceContextProvider to intercept the calls to the IsIdle method and route them to the CustomLeaseExtension. Die IInstanceContextProvider-Implementierung ist in der CustomLifetimeLease-Klasse enthalten.The IInstanceContextProvider implementation is contained in CustomLifetimeLease class. Die IsIdle Methode wird aufgerufen, wenn WCF Begriff ist, die Dienstinstanz freizugeben.The IsIdle method is invoked when WCF is about to release the service instance. Es gibt jedoch nur eine Instanz einer bestimmten ISharedSessionInstance-Implementierung in der IInstanceContextProvider-Auflistung von ServiceBehavior.However, there is only one instance of a particular ISharedSessionInstance implementation in the ServiceBehavior’s IInstanceContextProvider collection. Das bedeutet, dass es keine Möglichkeit, zu wissen, die InstanceContext geschlossen wird, die zum Zeitpunkt der WCF überprüft die IsIdle Methode.This means there is no way of knowing the InstanceContext being closed at the time WCF checks the IsIdle method. Aus diesem Grund werden Anforderungen der IsIdle-Methode in diesem Beispiel mit der Threadsperre serialisiert.Therefore this sample uses thread locking to serialize requests to the IsIdle method.

Wichtig

Die Verwendung der Threadsperre wird nicht empfohlen, da die Leistung der Anwendung durch die Serialisierung deutlich beeinträchtigt werden kann.Using thread locking is not a recommended approach because serialization can severely affect the performance of your application.

Eine private Membervariable wird in der CustomLeaseExtension-Klasse verwendet, um den IsIdle-Wert nachzuverfolgen.A private member variable is used in the CustomLeaseExtension class to track the IsIdle value. Jedes Mal, wenn der Wert von IInstanceContextProvider abgerufen wird, wird der private IsIdle-Member zurückgegeben und auf false zurückgesetzt.Each time the value of IInstanceContextProvider is retrieved the IsIdle private member is returned and reset to false. Dieser Wert muss auf false festgelegt werden, um sicherzustellen, dass der Verteiler die NotifyIdle-Methode aufruft.It is essential to set this value to false in order to make sure the Dispatcher calls the NotifyIdle method.

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

Wenn die ISharedSessionLifetime.IsIdle-Eigenschaft false zurückgibt, registriert der Verteiler mithilfe der NotifyIdle-Methode eine Rückruffunktion.If the ISharedSessionLifetime.IsIdle property returns false the Dispatcher registers a callback function by using the NotifyIdle method. Diese Methode empfängt einen Verweis darauf, dass InstanceContext freigegeben wird.This method receives a reference to the InstanceContext being released. Daher kann der Beispielcode die Erweiterung des Typs ICustomLease abfragen und die ICustomLease.IsIdle-Eigenschaft im erweiterten Zustand überprüfen.Therefore the sample code can query the ICustomLease type extension and check the ICustomLease.IsIdle property in the extended state.

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

Bevor die ICustomLease.IsIdle-Eigenschaft überprüft wird, muss die Rückrufeigenschaft festgelegt werden, damit die CustomLeaseExtension den Verteiler benachrichtigen kann, sobald sie in den Leerlauf wechselt.Before the ICustomLease.IsIdle property is checked the Callback property needs to be set as this is essential for CustomLeaseExtension to notify the Dispatcher when it becomes idle. Wenn ICustomLease.IsIdle true zurückgibt, wird der private isIdle-Member einfach in CustomLifetimeLease auf true festgelegt, und die Rückrufmethode wird vom Member aufgerufen.If ICustomLease.IsIdle returns true, the isIdle private member is simply set in CustomLifetimeLease to true and calls the callback method. Da im Code eine Sperre enthalten ist, können andere Threads den Wert dieses privaten Members nicht ändern.Because the code holds a lock, other threads cannot change the value of this private member. Wenn der Verteiler das nächste Mal die ISharedSessionLifetime.IsIdle-Eigenschaft überprüft, gibt sie true zurück, und der Verteiler kann die Instanz freigeben.And the next time Dispatcher checks the ISharedSessionLifetime.IsIdle, it returns true and lets Dispatcher release the instance.

Jetzt da die Vorarbeit für die benutzerdefinierte Erweiterung abgeschlossen ist, muss sie in das Dienstmodell eingebunden werden.Now that the groundwork for the custom extension is completed, it has to be hooked up to the service model. Zum Einbinden der CustomLeaseExtension -Implementierung, die die InstanceContext, WCF bietet die IInstanceContextInitializer Schnittstelle, um das bootstrapping von ausführen InstanceContext.To hook up the CustomLeaseExtension implementation to the InstanceContext, WCF provides the IInstanceContextInitializer interface to perform the bootstrapping of InstanceContext. In diesem Beispiel implementiert die CustomLeaseInitializer-Klasse diese Schnittstelle und fügt eine CustomLeaseExtension-Instanz zur Extensions-Auflistung aus der einzigen Methodeninitialisierung hinzu.In the sample, the CustomLeaseInitializer class implements this interface and adds an instance of CustomLeaseExtension to the Extensions collection from the only method initialization. Diese Methode wird vom Verteiler aufgerufen, während InstanceContext initialisiert wird.This method is called by Dispatcher while initializing the InstanceContext.

public void Initialize(InstanceContext instanceContext, Message message)  
{  
  IExtension<InstanceContext> customLeaseExtension =  
    new CustomLeaseExtension(timeout);  
  instanceContext.Extensions.Add(customLeaseExtension);  
}  

Schließlich die System.ServiceModel.Dispatcher.IShareableInstanceContextLifetime und IInstanceContextInitializer Implementierungen sind ist hakenförmigen bis zu das Dienstmodell mithilfe der IServiceBehavior Implementierung.Finally the System.ServiceModel.Dispatcher.IShareableInstanceContextLifetime and IInstanceContextInitializer implementations are is hooked up to the service model by using the IServiceBehavior implementation. Diese Implementierung wird in der CustomLeaseTimeAttribute-Klasse eingefügt, und sie wird außerdem von der Attribute-Basisklasse abgeleitet, um dieses Verhalten als Attribut verfügbar zu machen.This implementation is placed in the CustomLeaseTimeAttribute class and it also derives from the Attribute base class to expose this behavior as an attribute. In der IServiceBehavior.ApplyBehavior-Methode werden Instanzen von der IInstanceContextInitializer-Implementierung und der System.ServiceModel.Dispatcher.IShareableInstanceContextLifetime-Implementierung zu der System.ServiceModel.Dispatcher.DispatchRuntime.InstanceContextLifetimes-Auflistung bzw. der InstanceContextInitializers-Auflistung von <xref:System.ServiceModel.Dispatcher.IShareableInstanceContextLifetime> hinzugefügt.In the IServiceBehavior.ApplyBehavior method, instances of IInstanceContextInitializer and System.ServiceModel.Dispatcher.IShareableInstanceContextLifetime implementations are added to the System.ServiceModel.Dispatcher.DispatchRuntime.InstanceContextLifetimes and InstanceContextInitializers collections of the <xref:System.ServiceModel.Dispatcher.IShareableInstanceContextLifetime> respectively.

public void ApplyBehavior(ServiceDescription description,   
           ServiceHostBase serviceHostBase,   
           Collection<DispatchBehavior> behaviors,  
           Collection<BindingParameterCollection> parameters)  
{  
    CustomLifetimeLease customLease = new CustomLifetimeLease();  
    CustomLeaseInitializer initializer =   
                new CustomLeaseInitializer(timeout);  

    foreach (DispatchBehavior dispatchBehavior in behaviors)  
    {  
        dispatchBehavior.InstanceContextLifetimes.Add(customLease);  
        dispatchBehavior.InstanceContextInitializers.Add(initializer);  
    }  
}  

Dieses Verhalten kann einer Beispieldienstklasse hinzugefügt werden, indem es mit dem CustomLeaseTime-Attribut kommentiert wird.This behavior can be added to a sample service class by annotating it with the CustomLeaseTime attribute.

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

Wenn Sie das Beispiel ausführen, werden die Anforderungen und Antworten für den Vorgang im Dienst- und Clientkonsolenfenster angezeigt.When you run the sample, the operation requests and responses are displayed in both the service and client console windows. Drücken Sie die EINGABETASTE in den einzelnen Konsolenfenstern, um den Dienst und den Client zu schließen.Press ENTER in each console window to shut down the service and client.

So können Sie das Beispiel einrichten, erstellen und ausführenTo set up, build, and run the sample

  1. Stellen Sie sicher, dass Sie ausgeführt haben die Setupprozedur für die Windows Communication Foundation-Beispiele zum einmaligen.Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. Um die C#- oder Visual Basic .NET-Edition der Projektmappe zu erstellen, befolgen Sie die unter Building the Windows Communication Foundation Samplesaufgeführten Anweisungen.To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  3. Um das Beispiel in einer einzelnen oder computerübergreifenden Konfiguration ausführen möchten, folgen Sie den Anweisungen Ausführen der Windows Communication Foundation-Beispiele.To run the sample in a single- or cross-machine configuration, follow the instructions in Running the Windows Communication Foundation Samples.

Wichtig

Die Beispiele sind möglicherweise bereits auf dem Computer installiert.The samples may already be installed on your machine. Suchen Sie nach dem folgenden Verzeichnis (Standardverzeichnis), bevor Sie fortfahren.Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

Wenn dieses Verzeichnis nicht vorhanden ist, fahren Sie mit Windows Communication Foundation (WCF) und Windows Workflow Foundation (WF) Samples for .NET Framework 4 aller Windows Communication Foundation (WCF) herunterladen und WFWF Beispiele.If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF) and WFWF samples. Dieses Beispiel befindet sich im folgenden Verzeichnis.This sample is located in the following directory.

<InstallDrive>:\WF_WCF_Samples\WCF\Extensibility\Instancing\Lifetime

Siehe auchSee Also