Initialisierung der InstanziierungInstancing Initialization

Dieses Beispiel erweitert die Pooling durch Definieren einer Schnittstelle Sample IObjectControl, die passt die Initialisierung eines Objekts durch das Aktivieren und deaktivieren es an.This sample extends the Pooling sample by defining an interface, IObjectControl, which customizes the initialization of an object by activating and deactivating it. Der Client ruft Methoden auf, die das Objekt an den Pool zurückgeben und das Objekt nicht an den Pool zurückgeben.The client invokes methods that return the object to the pool and that do not return the object to the pool.

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.

ErweiterungspunkteExtensibility Points

Der erste Schritt beim Erstellen einer Windows Communication Foundation (WCF)-Erweiterung ist die zu verwendenden Erweiterungspunkt entscheiden.The first step in creating a Windows Communication Foundation (WCF) extension is to decide the extensibility point to use. In WCF der Begriff EndpointDispatcher bezieht sich auf eine Laufzeitkomponente verantwortlich, konvertieren eingehende Nachrichten in Methodenaufrufe für den Dienst des Benutzers konvertiert und Rückgabewerte von dieser Methode in eine ausgehende Nachricht .In WCF, the term EndpointDispatcher refers to a run-time component responsible for converting incoming messages into method invocations on the user’s service and for converting return values from that method to an outgoing message. Ein WCF-Dienst erstellt einen EndpointDispatcher für jeden Endpunkt.A WCF service creates an EndpointDispatcher for each endpoint.

Der EndpointDispatcher stellt mithilfe der EndpointDispatcher-Klasse die Erweiterung des Endpunktbereichs bereit (für alle vom Dienst empfangenen oder gesendeten Nachrichten).The EndpointDispatcher offers endpoint scope (for all messages received or sent by the service) extensibility using the EndpointDispatcher class. Mit dieser Klasse können Sie verschiedene Eigenschaften anpassen, die das Verhalten von EndpointDispatcher steuern.This class allows you to customize various properties that control the behavior of the EndpointDispatcher. In diesem Beispiel wird in erster Linie die InstanceProvider-Eigenschaft behandelt, die auf das Objekt zeigt, das die Instanzen der Dienstklasse bereitstellt.This sample focuses on the InstanceProvider property that points to the object that provides the instances of the service class.

IInstanceProviderIInstanceProvider

In WCF erstellt EndpointDispatcher Instanzen einer Dienstklasse mithilfe eines Instanz-Anbieters, implementiert die IInstanceProvider Schnittstelle.In WCF, the EndpointDispatcher creates instances of a service class by using an instance provider that implements the IInstanceProvider interface. Diese Schnittstelle verfügt über nur zwei Methoden:This interface has only two methods:

Der ObjektpoolThe Object Pool

Die ObjectPoolInstanceProvider-Klasse enthält die Implementierung des Objektpools.The ObjectPoolInstanceProvider class contains the implementation for the object pool. Diese Klasse implementiert die IInstanceProvider-Schnittstelle für die Interaktion mit der Dienstmodellebene.This class implements the IInstanceProvider interface to interact with the service model layer. Wenn EndpointDispatcher die GetInstance-Methode aufruft, erstellt die benutzerdefinierte Implementierung keine neue Instanz, sondern sucht ein vorhandenes Objekt in einem Pool im Speicher.When the EndpointDispatcher calls the GetInstance method, instead of creating a new instance, the custom implementation looks for an existing object in an in-memory pool. Wenn eines verfügbar ist, wird es zurückgegeben.If one is available, it is returned. Andernfalls überprüft ObjectPoolInstanceProvider, ob die ActiveObjectsCount-Eigenschaft (Anzahl der aus dem Pool zurückgegebenen Objekte) die maximale Poolgröße erreicht hat.Otherwise, ObjectPoolInstanceProvider checks whether the ActiveObjectsCount property (number of objects returned from the pool) has reached the maximum pool size. Wenn dies nicht der Fall ist, wird eine neue Instanz erstellt und an den Aufrufer zurückgegeben, und anschließend wird ActiveObjectsCount inkrementiert.If not, a new instance is created and returned to the caller and ActiveObjectsCount is subsequently incremented. Andernfalls wird eine Objekterstellungsanforderung für einen konfigurierten Zeitraum in die Warteschlange gestellt.Otherwise an object creation request is queued for a configured period of time. Die Implementierung für GetObjectFromThePool wird im folgenden Beispielcode dargestellt.The implementation for GetObjectFromThePool is shown in the following sample code.

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

Die benutzerdefinierte ReleaseInstance-Implementierung fügt die freigegebene Instanz dem Pool erneut hinzu und dekrementiert den ActiveObjectsCount-Wert.The custom ReleaseInstance implementation adds the released instance back to the pool and decrements the ActiveObjectsCount value. EndpointDispatcher kann diese Methoden von unterschiedlichen Threads aus aufrufen. Daher ist ein synchronisierter Zugriff auf die Member der Klassenebene in der ObjectPoolInstanceProvider-Klasse erforderlich.The EndpointDispatcher can call these methods from different threads, and therefore synchronized access to the class level members in the ObjectPoolInstanceProvider class is required.

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

Die ReleaseInstance Methode bietet eine bereinigungsinitialisierung Funktion.The ReleaseInstance method provides a clean up initialization feature. Normalerweise wird im Pool eine Mindestanzahl von Objekten für die Lebensdauer des Pools beibehalten.Normally the pool maintains a minimum number of objects for the lifetime of the pool. Es kann jedoch Zeiten mit übermäßiger Auslastung geben, für die im Pool zusätzliche Objekte erstellt werden müssen, um die in der Konfiguration festgelegte Höchstgrenze zu erreichen.However, there can be periods of excessive usage that require creating additional objects in the pool to reach the maximum limit specified in the configuration. Wenn der Pool weniger aktiv ist, stellen diese überzähligen Objekte einen zusätzlichen Aufwand dar.Eventually when the pool becomes less active those surplus objects can become an extra overhead. Wenn activeObjectsCount daher 0 (null) erreicht, wird ein Leerlaufzeitgeber gestartet, der einen Bereinigungszyklus auslöst und ausführt.Therefore when the activeObjectsCount reaches zero an idle timer is started that triggers and performs a clean-up cycle.

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

ServiceModel-Ebenenerweiterungen werden mithilfe der folgenden Verhalten verknüpft:ServiceModel layer extensions are hooked up using the following behaviors:

  • Dienstverhalten: Diese ermöglichen die Anpassung der ganzen Dienstlaufzeit.Service Behaviors: These allow for the customization of the entire service runtime.

  • Endpunktverhalten: Diese ermöglichen das Anpassen eines bestimmten Dienstendpunkts, einschließlich EndpointDispatcher.Endpoint Behaviors: These allow for the customization of a particular service endpoint, including the EndpointDispatcher.

  • Vertragsverhalten: Diese ermöglichen das Anpassen von ClientRuntime-Klassen oder DispatchRuntime-Klassen auf dem Client bzw. Server.Contract Behaviors: These allow for the customization of either ClientRuntime or DispatchRuntime classes on the client or the service respectively.

  • Vorgangsverhalten: Diese ermöglichen das Anpassen von ClientOperation-Klassen oder DispatchOperation-Klassen auf dem Client bzw. Server.Operation Behaviors: These allow for the customization of either ClientOperation or DispatchOperation classes on the client or the service respectively.

Für den Zweck einer Objektpoolingerweiterung kann ein Endpunktverhalten oder ein Dienstverhalten erstellt werden.For the purpose of an object pooling extension, either an endpoint behavior or a service behavior can be created. In diesem Beispiel wird ein Dienstverhalten verwendet, das die Objektpoolingfähigkeit auf alle Endpunkte des Diensts anwendet.In this example, we use a service behavior, which applies object pooling ability to every endpoint of the service. Dienstverhaltensweisen werden durch Implementieren der IServiceBehavior-Schnittstelle erstellt.Service behaviors are created by implementing the IServiceBehavior interface. Es gibt mehrere Möglichkeiten, ServiceModel auf die benutzerdefinierten Verhaltensweisen hinzuweisen:There are several ways to make the ServiceModel aware of the custom behaviors:

  • Verwenden eines benutzerdefinierten Attributs.Using a custom attribute.

  • Imperatives Hinzufügen zur Verhaltensauflistung der Dienstbeschreibung.Imperatively adding it to the service description’s behaviors collection.

  • Erweitern der Konfigurationsdatei.Extending the configuration file.

In diesem Beispiel wird ein benutzerdefiniertes Attribut verwendet.This sample uses a custom attribute. Beim Erstellen von ServiceHost werden die in der Typdefinition des Diensts verwendeten Attribute untersucht, und die verfügbaren Verhalten werden der Verhaltensauflistung der Dienstbeschreibung hinzugefügt.When the ServiceHost is constructed, it examines the attributes used in the service’s type definition and adds the available behaviors to the service description’s behaviors collection.

Die IServiceBehavior Schnittstelle verfügt über drei Methoden: Validate , AddBindingParameters , und ApplyDispatchBehavior.The IServiceBehavior interface has three methods: Validate, AddBindingParameters, and ApplyDispatchBehavior. Diese Methoden werden aufgerufen, indem Sie WCF bei der ServiceHost initialisiert wird.These methods are called by WCF when the ServiceHost is being initialized. IServiceBehavior.Validate wird zuerst aufgerufen. So kann der Dienst auf Inkonsistenzen untersucht werden.IServiceBehavior.Validate is called first; it allows the service to be inspected for inconsistencies. IServiceBehavior.AddBindingParameters wird danach aufgerufen. Diese Methode ist nur in sehr komplexen Szenarios erforderlich.IServiceBehavior.AddBindingParameters is called next; this method is only required in very advanced scenarios. IServiceBehavior.ApplyDispatchBehavior wird zuletzt aufgerufen und ist für das Konfigurieren der Laufzeit zuständig.IServiceBehavior.ApplyDispatchBehavior is called last and is responsible for configuring the runtime. Die folgenden Parameter werden in IServiceBehavior.ApplyDispatchBehavior übergeben:The following parameters are passed into IServiceBehavior.ApplyDispatchBehavior:

  • Description: Dieser Parameter stellt die Dienstbeschreibung für den gesamten Dienst bereit.Description: This parameter provides the service description for the entire service. Dies kann verwendet werden, um Beschreibungsdaten über die Endpunkte, Verträge, Bindungen und andere Daten zu dem Dienst zu überprüfen.This can be used to inspect description data about the service’s endpoints, contracts, bindings, and other data associated with the service.

  • ServiceHostBase: Dieser Parameter stellt die ServiceHostBase bereit, die gerade initialisiert wird.ServiceHostBase: This parameter provides the ServiceHostBase that is currently being initialized.

In der benutzerdefinierten IServiceBehavior-Implementierung wird eine neue Instanz von ObjectPoolInstanceProvider instanziiert und der InstanceProvider-Eigenschaft in jedem EndpointDispatcher zugewiesen, der ServiceHostBase angefügt ist.In the custom IServiceBehavior implementation, a new instance of ObjectPoolInstanceProvider is instantiated and assigned to the InstanceProvider property in each EndpointDispatcher that is attached to the 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;  
                 }  
             }  
         }  
     }  
}   

Neben einer IServiceBehavior-Implementierung verfügt die ObjectPoolingAttribute-Klasse über mehrere Member zum Anpassen des Objektpools mithilfe der Attributargumente.In addition to an IServiceBehavior implementation the ObjectPoolingAttribute class has several members to customize the object pool using the attribute arguments. Diese Member umfassen MaxSize, MinSize, Enabled und CreationTimeout für die Übereinstimmung mit dem von .NET Enterprise Services bereitgestellten Objektpooling-Featuresatz.These members include MaxSize, MinSize, Enabled and CreationTimeout, to match the object pooling feature set provided by .NET Enterprise Services.

Objektpooling Verhalten kann jetzt an einen WCF-Dienst hinzugefügt werden, durch das Hinzufügen der dienstimplementierung mit dem neu erstellten, benutzerdefinierten ObjectPooling Attribut.The object pooling behavior can now be added to a WCF service by annotating the service implementation with the newly created custom ObjectPooling attribute.

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

Aktivieren und Deaktivieren von VerknüpfungenHooking Activation and Deactivation

Das primäre Ziel des Objektpoolings ist das Optimieren von Objekten mit kurzer Lebensdauer und relativ aufwändiger Erstellung und Initialisierung.The primary objective of object pooling is to optimize short-lived objects with relatively expensive creation and initialization. Bei der richtigen Verwendung kann daher eine erhebliche Leistungssteigerung erreicht werden.Therefore it can give a dramatic performance boost to an application if properly used. Da das Objekt aus dem Pool zurückgegeben wird, wird der Konstruktor nur einmal aufgerufen.Because the object is returned from the pool, the constructor is called only once. Bei einigen Anwendungen ist jedoch eine gewisse Kontrolle erforderlich, damit sie die in einem einzigen Kontext verwendeten Ressourcen initialisieren und bereinigen können.However, some applications require some level of control so that they can initialize and clean-up the resources used during a single context. Ein Objekt, das beispielsweise für eine Gruppe von Berechnungen verwendet wird, kann die privaten Felder zurücksetzen, bevor die nächste Berechnung verarbeitet wird.For example, an object being used for a set of calculations can reset its private fields before processing the next calculation. In Enterprise Services wurde diese Art der kontextspezifischen Initialisierung ermöglicht, indem der Objektentwickler die Activate-Methode und die Deactivate-Methode in der ServicedComponent-Basisklasse überschreiben konnte.Enterprise Services enabled this kind of context-specific initialization by letting the object developer override Activate and Deactivate methods from the ServicedComponent base class.

Der Objektpool ruft die Activate-Methode unmittelbar vor dem Zurückgeben des Objekts aus dem Pool auf.The object pool calls the Activate method just before returning the object from the pool. Deactivate wird aufgerufen, wenn das Objekt an den Pool zurückgegeben wird.Deactivate is called when the object returns back to the pool. Die ServicedComponent-Basisklasse verfügt außerdem über die boolean-Eigenschaft mit der Bezeichnung CanBePooled, mit der der Pool darüber benachrichtigt werden kann, ob das Objekt weiter gepoolt werden kann.The ServicedComponent base class also has a boolean property called CanBePooled, which can be used to notify the pool whether the object can be pooled further.

Im Beispiel wird eine öffentliche Schnittstelle (IObjectControl) deklariert, die über die oben genannten Member verfügt, um diese Funktionalität zu imitieren.To mimic this functionality, the sample declares a public interface (IObjectControl) that has the aforementioned members. Diese Schnittstelle wird dann von Dienstklassen implementiert, die die kontextspezifische Initialisierung bereitstellen sollen.This interface is then implemented by service classes intended to provide context specific initialization. Die IInstanceProvider-Implementierung muss geändert werden, um diese Anforderungen zu erfüllen.The IInstanceProvider implementation must be modified to meet these requirements. Jetzt, jedes Mal Sie Abrufen eines Objekts durch Aufrufen der GetInstance -Methode, müssen Sie überprüfen, ob das Objekt implementiert IObjectControl. Wenn dies der Fall ist, müssen Sie Aufrufen der Activate Methode entsprechend.Now, each time you get an object by calling the GetInstance method, you must check whether the object implements IObjectControl. If it does, you must call the Activate method appropriately.

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

Beim Zurückgeben eines Objekts an den Pool ist eine Überprüfung für die CanBePooled-Eigenschaft erforderlich, bevor das Objekt erneut dem Pool hinzugefügt wird.When returning an object to the pool, a check is required for the CanBePooled property before adding the object back to the pool.

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

Da der Dienstentwickler entscheiden kann, ob ein Objekt gepoolt werden kann, kann die Objektanzahl im Pool zu einem bestimmten Zeitpunkt unter dem Mindestwert liegen.Because the service developer can decide whether an object can be pooled, the object count in the pool at a given time can go below the minimum size. Sie müssen daher überprüfen, ob die Objektanzahl unter dem Mindestwert liegt, und die erforderliche Initialisierung in der Bereinigungsprozedur ausführen.Therefore you must check whether the object count has gone below the minimum level and perform the necessary initialization in the clean-up procedure.

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

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. Führen Sie zum Erstellen der Projektmappe die Anweisungen im Erstellen der Windows Communication Foundation-Beispiele.To build 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\Initialization

Siehe auchSee Also