Sitzungen und WarteschlangenSessions and Queues

Dieses Beispiel veranschaulicht, wie ein Satz zusammengehöriger Nachrichten bei der Kommunikation unter Verwendung von Warteschlangen über den MSMQ-Transport (Message Queuing) gesendet und empfangen wird.This sample demonstrates how to send and receive a set of related messages in queued communication over the Message Queuing (MSMQ) transport. In diesem Beispiel wird die netMsmqBinding-Bindung verwendet.This sample uses the netMsmqBinding binding. Der Dienst ist eine selbst gehostete Konsolenanwendung, die es Ihnen ermöglicht, den Dienst beim Empfang von Nachrichten in der Warteschlange zu beobachten.The service is a self-hosted console application to enable you to observe the service receiving queued messages.

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.

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, rufen Sie Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 auf, um alle Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) - und WFWF -Beispiele herunterzuladen.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)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\Basic\Binding\Net\MSMQ\Session

In einer Warteschlangenkommunikation kommuniziert der Client über eine Warteschlange mit dem Dienst.In queued communication, the client communicates to the service using a queue. Genauer ausgedrückt bedeutet dies, dass der Client Nachrichten an eine Warteschlange sendet.More precisely, the client sends messages to a queue. Der Dienst empfängt Nachrichten aus der Warteschlange.The service receives messages from the queue. Folglich müssen der Dienst und der Client nicht gleichzeitig ausgeführt werden, um über eine Warteschlange zu kommunizieren.The service and client therefore, do not have to be running at the same time to communicate using a queue.

Manchmal sendet ein Client eine Reihe von Nachrichten, die in einer Gruppe zusammengehören.Sometimes, a client sends a set of messages that are related to each other in a group. Wenn Nachrichten zusammen oder in einer angegebenen Reihenfolge verarbeitet werden müssen, können Sie mithilfe einer Warteschlange zwecks Verarbeitung durch eine einzige Empfangsanwendung zusammengefasst werden.When messages must be processed together or in a specified order, a queue can be used to group them together, for processing by a single receiving application. Dies ist besonders wichtig, wenn in einer Gruppe von Servern mehrere Empfangsanwendungen vorhanden sind und sichergestellt werden muss, dass eine Gruppe von Nachrichten von derselben empfangenden Anwendung verarbeitet wird.This is particularly important when there are several receiving applications on a group of servers and it is necessary to ensure that a group of messages is processed by the same receiving application. Warteschlangensitzungen sind ein Mechanismus zum Senden und Empfangen eines Satzes zusammengehöriger Nachrichten, die alle zusammen verarbeitet werden müssen.Queued sessions are a mechanism used to send and receive a related set of messages that must get processed all at once. Damit Warteschlangensitzungen dieses Muster bieten, ist eine Transaktion erforderlich.Queued sessions require a transaction to exhibit this pattern.

Im vorliegenden Beispiel sendet der Client im Rahmen einer Sitzung innerhalb des Bereichs einer einzigen Transaktion eine Reihe von Nachrichten an den Dienst.In the sample, the client sends a number of messages to the service as part of a session within the scope of a single transaction.

Der Dienstvertrag ist IOrderTaker, der einen unidirektionalen Dienst definiert, der für die Verwendung mit Warteschlangen geeignet ist.The service contract is IOrderTaker, which defines a one-way service that is suitable for use with queues. Der in dem Vertrag im folgenden Beispielcode verwendete SessionMode zeigt an, dass die Nachrichten zu der Sitzung gehören.The SessionMode used in the contract shown in the following sample code indicates that the messages are part of the session.

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]  
public interface IOrderTaker  
{  
    [OperationContract(IsOneWay = true)]  
    void OpenPurchaseOrder(string customerId);  

    [OperationContract(IsOneWay = true)]  
    void AddProductLineItem(string productId, int quantity);  

    [OperationContract(IsOneWay = true)]  
    void EndPurchaseOrder();  
}  

Der Dienst definiert Dienstvorgänge so, dass der erste Vorgang in einer Transaktion eingetragen, diese jedoch nicht automatisch abgeschlossen wird.The service defines service operations in such a way that the first operation enlists in a transaction but does not automatically complete the transaction. Auch die nachfolgenden Vorgänge werden in derselben Transaktion eingetragen, die aber nicht automatisch abgeschlossen wird.Subsequent operations also enlist in the same transaction but do not automatically complete. Der letzte Vorgang in der Sitzung schließt die Transaktion automatisch ab.The last operation in the session automatically completes the transaction. So wird die gleiche Transaktion für mehrere Vorgangsaufrufe im Dienstvertrag verwendet.Thus, the same transaction is used for several operation invocations in the service contract. Wenn einer der Vorgänge eine Ausnahme auslöst, wird ein Rollback der Transaktion ausgeführt und die Sitzung zurück in die Warteschlange gelegt.If any of the operations throw an exception, then the transaction rolls back and the session is put back into the queue. Nach erfolgreichem Abschluss des letzten Vorgangs wird ein Commit für die Transaktion ausgeführt.Upon successful completion of the last operation, the transaction is committed. Der Dienst verwendet PerSession als InstanceContextMode, um sämtliche Nachrichten in einer Sitzung in derselben Instanz des Diensts zu empfangen.The service uses PerSession as the InstanceContextMode to receive all messages in a session on the same instance of the service.

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]  
public class OrderTakerService : IOrderTaker  
{  
    PurchaseOrder po;  

    [OperationBehavior(TransactionScopeRequired = true,   
                                 TransactionAutoComplete = false)]  
    public void OpenPurchaseOrder(string customerId)  
    {  
        Console.WriteLine("Creating purchase order");  
        po = new PurchaseOrder(customerId);  
    }  

    [OperationBehavior(TransactionScopeRequired = true,   
                                  TransactionAutoComplete = false)]  
    public void AddProductLineItem(string productId, int quantity)  
    {  
        po.AddProductLineItem(productId, quantity);  
        Console.WriteLine("Product " + productId + " quantity " +   
                            quantity + " added to purchase order");  
    }  

    [OperationBehavior(TransactionScopeRequired = true,   
                                  TransactionAutoComplete = true)]  
    public void EndPurchaseOrder()  
    {  
       Console.WriteLine("Purchase Order Completed");  
       Console.WriteLine();  
       Console.WriteLine(po.ToString());  
    }  
}  

Der Dienst ist selbst gehostet.The service is self hosted. Bei Verwendung des MSMQ-Transports muss die Warteschlange im Voraus erstellt werden.When using the MSMQ transport, the queue used must be created in advance. Dies kann manuell erfolgen oder mithilfe eines Codes.This can be done manually or through code. In diesem Beispiel enthält der Dienst System.Messaging-Code, um zu überprüfen, ob die Warteschlange bereits vorhanden ist, und um sie andernfalls zu erstellen.In this sample, the service contains System.Messaging code to check for the existence of the queue and creates it, if necessary. Der Warteschlangenname wird mithilfe der AppSettings-Klasse aus der Konfigurationsdatei gelesen.The queue name is read from the configuration file using the AppSettings class.

// Host the service within this EXE console application.  
public static void Main()  
{  
    // Get MSMQ queue name from app settings in configuration.  
    string queueName = ConfigurationManager.AppSettings["queueName"];  

    // Create the transacted MSMQ queue if necessary.  
    if (!MessageQueue.Exists(queueName))  
        MessageQueue.Create(queueName, true);  

    // Create a ServiceHost for the OrderTakerService type.  
    using (ServiceHost serviceHost = new ServiceHost(typeof(OrderTakerService)))  
    {  
        // Open the ServiceHost to create listeners and start listening for messages.  
        serviceHost.Open();  

        // The service can now be accessed.  
        Console.WriteLine("The service is ready.");  
        Console.WriteLine("Press <ENTER> to terminate service.");  
        Console.WriteLine();  
        Console.ReadLine();  

        // Close the ServiceHost to shutdown the service.  
        serviceHost.Close();   
    }  
}  

Der MSMQ-Warteschlangenname wird im appSettings-Abschnitt der Konfigurationsdatei angegeben.The MSMQ queue name is specified in an appSettings section of the configuration file. Der Endpunkt für den Dienst wird im Abschnitt system.serviceModel der Konfigurationsdatei definiert und gibt die netMsmqBinding-Bindung an.The endpoint for the service is defined in the system.serviceModel section of the configuration file and specifies the netMsmqBinding binding.

<appSettings>  
  <!-- Use appSetting to configure MSMQ queue name. -->  
  <add key="queueName" value=".\private$\ServiceModelSamplesSession" />  
</appSettings>  

<system.serviceModel>  
  <services>  
    <service name="Microsoft.ServiceModel.Samples.OrderTakerService"  
        behaviorConfiguration="CalculatorServiceBehavior">  
      ...  
      <!-- Define NetMsmqEndpoint -->  
      <endpoint address="net.msmq://localhost/private/ServiceModelSamplesSession"  
                binding="netMsmqBinding"  
                contract="Microsoft.ServiceModel.Samples.IOrderTaker" />  
      ...  
    </service>  
  </services>  
  ...  
<system.serviceModel>  

Der Client erstellt einen Geltungsbereich für die Transaktion.The client creates a transaction scope. Alle Nachrichten in der Sitzung werden an die Warteschlange innerhalb des Transaktionsbereichs gesendet, wo sie als eine unteilbare Einheit behandelt werden, so dass sämtliche Nachrichten entweder erfolgreich sind oder fehlschlagen.All messages in the session are sent to the queue within the transaction scope, causing it to be treated as an atomic unit where all messages succeed or fail. Das Commit für die Transaktion wird durch Aufrufen von Complete ausgeführt.The transaction is committed by calling Complete.

//Create a transaction scope.  
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))  
{  
    // Create a client with given client endpoint configuration.  
    OrderTakerClient client = new OrderTakerClient("OrderTakerEndpoint");  
    // Open a purchase order.  
    client.OpenPurchaseOrder("somecustomer.com");  
    Console.WriteLine("Purchase Order created");  

    // Add product line items.  
    Console.WriteLine("Adding 10 quantities of blue widget");  
    client.AddProductLineItem("Blue Widget", 10);  

    Console.WriteLine("Adding 23 quantities of red widget");  
    client.AddProductLineItem("Red Widget", 23);  

    // Close the purchase order.  
    Console.WriteLine("Closing the purchase order");  
    client.EndPurchaseOrder();  

    //Closing the client gracefully closes the connection and cleans up resources.  
    client.Close();                  

    // Complete the transaction.  
    scope.Complete();  
}  

Hinweis

Sie können für sämtliche Nachrichten in der Sitzung nur eine einzige Transaktion verwenden, und alle Nachrichten in der Sitzung müssen vor deren Commit gesendet werden.You can use only a single transaction for all messages in the session and all messages in the session must be sent before committing the transaction. Wenn der Client geschlossen wird, wird auch die Sitzung geschlossen.Closing the client closes the session. Daher muss der Client geschlossen werden, bevor die Transaktion abgeschlossen ist, um alle Nachrichten in der Sitzung an die Warteschlange zu senden.Therefore, the client has to be closed before the transaction is completed to send all messages in the session to the queue.

Wenn Sie das Beispiel ausführen, werden die Client- und Dienstaktivitäten sowohl im Dienst- als auch im Clientkonsolenfenster angezeigt.When you run the sample, the client and service activities are displayed in both the service and client console windows. Sie können sehen, wie der Dienst Nachrichten vom Client empfängt.You can see the service receive messages from the client. 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. Beachten Sie, dass aufgrund der Verwendung einer Warteschlange der Client und der Dienst nicht gleichzeitig ausgeführt werden müssen.Note that because queuing is in use, the client and service do not have to be up and running at the same time. Sie können den Client ausführen, ihn schließen und anschließend den Dienst starten, der dann trotzdem noch die Nachrichten des Clients empfängt.You can run the client, shut it down, and then start up the service and it still receives its messages.

Auf dem Client.On the client.

Purchase Order created  
Adding 10 quantities of blue widget  
Adding 23 quantities of red widget  
Closing the purchase order  

Press <ENTER> to terminate client.  

Beim Dienst.On the service.

The service is ready.  
Press <ENTER> to terminate service.  

Creating purchase order  
Product Blue Widget quantity 10 added to purchase order  
Product Red Widget quantity 23 added to purchase order  
Purchase Order Completed  

Purchase Order: 7c86fef0-2306-4c51-80e6-bcabcc1a6e5e  
        Customer: somecustomer.com  
        OrderDetails  
                Order LineItem: 10 of Blue Widget @unit price: $2985  
                Order LineItem: 23 of Red Widget @unit price: $156  
        Total cost of this order: $33438  
        Order status: Pending  

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 C#-, C++ oder Visual Basic .NET Edition der Lösung die Anweisungen im Erstellen der Windows Communication Foundation-Beispiele.To build the C#, 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.

Standardmäßig wird mit NetMsmqBinding die Transportsicherheit aktiviert.By default with the NetMsmqBinding, transport security is enabled. Es nämlich gibt zwei relevante Eigenschaften für MSMQ-transportsicherheit MsmqAuthenticationMode und MsmqProtectionLevel . standardmäßig der Authentifizierungsmodus festgelegt ist, um Windows und die Schutzebene festgelegt ist, um Sign.There are two relevant properties for MSMQ transport security namely, MsmqAuthenticationMode and MsmqProtectionLevel. By default, the authentication mode is set to Windows and the protection level is set to Sign. Damit MSMQ die Authentifizierungs- und Signierungsfunktion bereitstellt, muss es Teil einer Domäne sein, und die Active Directory-Integrationsoption für MSMQ muss installiert sein.For MSMQ to provide the authentication and signing feature, it must be part of a domain and the active directory integration option for MSMQ must be installed. Wenn Sie dieses Beispiel auf einem Computer ausführen, der diese Kriterien nicht erfüllt, tritt ein Fehler auf.If you run this sample on a computer that does not satisfy these criteria you receive an error.

So führen Sie das Beispiel auf einem Computer aus, der sich in einer Arbeitsgruppe befindet oder über keine Active Directory-Integration verfügtTo run the sample on a computer joined to a workgroup or without active directory integration

  1. Wenn Ihr Computer nicht zu einer Domäne gehört oder auf ihm keine Active Directory-Integration installiert ist, deaktivieren Sie die Transportsicherheit, indem Sie den Authentifizierungsmodus und die Schutzebene auf None setzen, wie in der folgenden Beispielkonfiguration gezeigt.If your computer is not part of a domain or does not have active directory integration installed, turn off transport security by setting the authentication mode and protection level to None as shown in the following sample configuration.

    <system.serviceModel>  
      <services>  
        <service name="Microsoft.ServiceModel.Samples.OrderTakerService"  
                 behaviorConfiguration="OrderTakerServiceBehavior">  
          <host>  
            <baseAddresses>  
              <add baseAddress=  
             "http://localhost:8000/ServiceModelSamples/service"/>  
            </baseAddresses>  
          </host>  
          <!-- Define NetMsmqEndpoint -->  
          <endpoint  
              address=  
            "net.msmq://localhost/private/ServiceModelSamplesSession"  
              binding="netMsmqBinding"  
              bindingConfiguration="Binding1"  
           contract="Microsoft.ServiceModel.Samples.IOrderTaker" />  
          <!-- The mex endpoint is exposed at-->      
          <!--http://localhost:8000/ServiceModelSamples/service/mex. -->  
          <endpoint address="mex"  
                    binding="mexHttpBinding"  
                    contract="IMetadataExchange" />  
        </service>  
      </services>  
    
      <bindings>  
        <netMsmqBinding>  
          <binding name="Binding1">  
            <security mode="None" />  
          </binding>  
        </netMsmqBinding>  
      </bindings>  
    
        <behaviors>  
          <serviceBehaviors>  
            <behavior name="OrderTakerServiceBehavior">  
              <serviceMetadata httpGetEnabled="True"/>  
            </behavior>  
          </serviceBehaviors>  
        </behaviors>  
    
      </system.serviceModel>  
    
  2. Ändern Sie die Konfiguration sowohl auf dem Server als auch auf dem Client, bevor Sie das Beispiel ausführen.Ensure that you change the configuration on both the server and the client before you run the sample.

    Hinweis

    Das Einstellen des Sicherheitsmodus auf None ist dasselbe, wie MsmqAuthenticationMode, MsmqProtectionLevel und Message-Sicherheit auf None zu setzen.Setting security mode to None is equivalent to setting MsmqAuthenticationMode, MsmqProtectionLevel, and Message security to None.

Siehe auchSee Also