Freigeben über


Beispiel zu Duplexworkflowdienst

In diesem Beispiel wird veranschaulicht, wie eine asynchrone Duplexkommunikation zwischen zwei kommunizierenden Diensten ausgeführt wird. In dem Beispiel wird außerdem gezeigt, wie die Kommunikation vom lokalen Host zum Workflow mithilfe von Nachrichten ausgeführt wird. Beim Ausführen der Duplexkommunikation zwischen zwei Diensten müssen die beiden Dienste einen Kontext austauschen, damit die Kommunikation in beide Richtungen erfolgen kann. Der Dienst, der die Kommunikation initiiert, empfängt den Kontext in der Antwort auf seine Nachricht. Damit die Kommunikation vom empfangenden Dienst zum initiierenden Dienst unterstützt wird, muss der initiierende Dienst die Kontextinformationen in der ersten Nachricht senden.

Tipp

Zum Erstellen und Ausführen dieses Beispiels muss .NET Framework, Version 3.5 installiert sein. Zum Öffnen des Projekts und der Projektmappendateien ist Visual Studio 2008 erforderlich.

Weitere Informationen zum Einrichten dieses Beispiels finden Sie unter One-time Setup Procedure for Windows Communication Foundation Samples.

Nachrichten werden auch für die Kommunikation zwischen dem lokalen Host und dem Dienst verwendet. Der lokale Host macht einen bekannten Endpunkt verfügbar, den der Dienst für den Rückruf verwenden kann. In diesem Beispiel wird ein LocalWorkflowServiceHost-Typ implementiert, der die Funktionen zum Erstellen des lokalen Listeners sowie des Workflowdiensthosts für den gehosteten Dienst bereitstellt.

Architektur eines Duplexworkflowdienst-Beispiels

Dieses Beispiel umfasst die folgenden kommunizierenden Entitäten:

  • Clienthost
    Der Clienthost kommuniziert mit dem Clientworkflow, indem er Vorgänge in IReverseContract aufruft. Wenn der Clienthost zuerst den BeginWork-Vorgang aufruft, wird der Clientworkflow erstellt. Als Reaktion auf den BeginWork-Vorgang sendet der Clientworkflow eine Nachricht zurück, die den Kontext für den Clientworkflow enthält. Der vom Host für die Kommunikation mit dem Clientworkflow erstellte Kanal verfügt nun über den Kontext für die weitere Kommunikation. In diesem Beispiel wird veranschaulicht, wie der Clienthost mit einem Kanal mehrere Arbeitsaufgaben an den Clientworkflow sendet.
    Damit der Workflow mit dem Clienthost kommuniziert, verfügt der Clienthost über einen bekannten Endpunkt, über den die Überwachung erfolgt. In diesem Beispiel ist der bekannte Endpunkt HostEndPoint. Mit dem LocalWorkflowServiceHost werden dieser bekannte Endpunkt für den Clienthost und der Workflowdiensthost für den Clientworkflow erstellt.

    LocalWorkflowServiceHost localHost = new LocalWorkflowServiceHost(typeof(ClientWorkflow),new ClientHost());
    localHost.WorkflowRuntime.WorkflowTerminated += 
    delegate(object sender, WorkflowTerminatedEventArgs e) 
    {
        Console.WriteLine("WorkflowTerminated: " + e.Exception.Message);
    };
    localHost.WorkflowRuntime.WorkflowCompleted += 
    delegate(object sender, WorkflowCompletedEventArgs e) 
    { 
        Console.WriteLine("WorkflowCompleted: " + 
                         e.WorkflowInstance.InstanceId.ToString()); 
    };
    localHost.Open();
    
  • Clientworkflow (als Dienst verfügbar gemacht)
    Der Clientworkflow implementiert IReverseContract. Der Dienstworkflow kommuniziert damit, wie in der oben stehenden Abbildung dargestellt, mit dem Clientworkflow. Der Clienthost ruft zuerst den BeginWorkflow-Vorgang auf, der den Clientworkflow erstellt. Die Antwort gibt den Kontext für den Dienstworkflow zurück, der in der folgenden Kommunikation des Clientworkflows mit dem Dienstworkflow verwendet wird. Als Teil des BeginWorkflow-Vorgangs übergibt der Clientworkflow seinen eigenen Endpunktverweis, der die Endpunktadresse sowie die Kontextheader enthält, an den Dienstworkflow. Der Dienstworkflow verwendet diese Endpunktadresse, um asynchron mit dem Clientworkflow zu kommunizieren.
    Der WaitForBeginWork-Ereignishandler im Ausgangszustand implementiert die Codeaktivität DoSetReturnAddress. Diese Aktivität legt den Endpunktverweis fest, der an den Dienstworkflow gesendet wird, wie im folgenden Beispiel dargestellt.

    private void SetReturnAddress(object sender, EventArgs e)
    {
        EndpointAddress epr = 
                  ContextManager.CreateEndpointAddress(ReturnUri, 
                                  this.ReceiveWorkItemComplete);
        ReturnAddress = EndpointAddress10.FromEndpointAddress(epr);
        DebugOutput("[ClientWorkflow:SetReturnAddress] " + 
                              epr.Headers[0].GetValue<string>());
    }
    
  • Diensthost
    In diesem Beispiel wird ein Workflowdiensthost implementiert. Dieser öffnet einen Listener, der Anforderungen vom Client überwacht. Die erste Anforderung vom Client erstellt eine Instanz des Dienstworkflows. Alle folgenden Anforderungen werden an die gleiche Workflowinstanz weitergeleitet, da die Anforderungen den Kontext im Nachrichtenheader enthalten.

  • Dienstworkflow (als Dienst verfügbar gemacht)
    Der Dienstworkflow implementiert IForwardContract. Der Dienstworkflow im BeginWorkflow-Vorgang empfängt den Endpunktverweis für den Clientworkflow. Der Dienstworkflow wendet diesen Endpunktverweis auf die Send-Aktivität an, die eine Nachricht asynchron an den Clientworkflow sendet. Der WaitForBeginWorkflow-Ereignishandler stellt die BeginWorkflow-Empfangsaktivität bereit. In der Empfangsaktivität ist die Codeaktivität ApplyReturnAddress vorhanden, die mithilfe der Rückgabeadresse in der Sendeaktivität eine Nachricht an den Clientworkflow sendet, wie im folgenden Beispiel dargestellt.

    private void ApplyReturnAddress(object sender, EventArgs e)
    {
        // apply ReturnAddress to ReverseEndpoint
        EndpointAddress epr = ReturnAddress.ToEndpointAddress();
        ContextManager.ApplyEndpointAddress(
                              this.SendWorkItemComplete, epr);
        DebugOutput("[ServiceWorkflow:ApplyReturnAddress] " + 
                           epr.Headers[0].GetValue<string>());
    }
    

    Die LocalWorkflowServiceHost-Klasse erstellt die erforderliche Infrastruktur für die Kommunikation vom Host zum Workflow. Der lokale Workflowdienst führt zwei Hauptaufgaben aus:

    • Erstellt einen lokalen Listener für den Host zur Überwachung von Nachrichten vom Workflow.
    • Instanziiert WorkflowServiceHost, um einen Listener für den Workflow zu erstellen.

    Die Klasse stellt außerdem Hilfsfunktionen bereit, mit denen der Host den Kontext für die Kommunikation mit dem Workflow beibehalten kann. Wenn der Host wiederverwendet wird, wird dieser Kontext für die Kommunikation mit der Workflowinstanz verwendet.

Das WorkflowServiceUtility-Projekt stellt alle Hilfsfunktionen bereit, die zum Bearbeiten des Kontexts erforderlich sind. Es werden Funktionen zum Extrahieren des Kontexts aus dem Kanal, Anwenden des Kontexts auf einen Kanal und Anwenden einer Endpunktadresse auf die Sendeaktivität bereitgestellt.

So richten Sie das Beispiel ein, erstellen es und führen es aus

  1. Führen Sie zum Installieren der Persistenz-Anbieter das Skript CreateStores.cmd im Thema One-Time Setup Procedure for the Windows Communication Foundation Samples aus.

  2. Laden Sie das Workflowdienstdienstprogramme herunter, und speichern Sie es so, dass sich der Ordner DuplexWorkflowService und der Ordner WorkflowServiceUtility im gleichen übergeordneten Ordner befinden.

  3. Wenn Sie keine Persistenz-Anbieter verwenden möchten, kommentieren Sie den Abschnitt <WorkflowRuntime> in den App.config-Dateien aus.

  4. In diesem Beispiel werden zwei Persistenzdatenbanken verwendet. Der Dienstworkflow verwendet NetFx35Samples_ServiceWorkflowStore, und der Client verwendet NetFx35Samples_ClientWorkflowStore. Sie können diese Speicher in SQL Server oder SQL Server Express erstellen. In den aktuellen Verbindungszeichenfolgen in den App.config-Dateien wird davon ausgegangen, dass Sie SQL Server Express verwenden. Wenn Sie die Speicher in SQL Server erstellen, stellen Sie sicher, dass Sie die Verbindungszeichenfolgen in den App.config-Dateien ändern.

  5. Wenn der Clienthost und der Diensthost ausgeführt werden, drücken Sie im Konsolenfenster Y, um Arbeitsaufgaben zu verarbeiten. Sie können mehrere Arbeitsaufgaben zur Verarbeitung senden. Wenn Sie den Client schließen und neu starten, wird er an dem Punkt fortgesetzt, an dem er geschlossen wurde.

  6. Wenn Sie die Dauerhaftigkeit der Dienste überprüfen möchten, schließen Sie die Client- und die Dienstanwendung, und starten Sie dann zunächst die Clientanwendung und anschließend die Dienstanwendung neu. Diese Reihenfolge ist wichtig, denn sobald der Dienstworkflow ausgeführt wird, versucht er, Nachrichten zurück an den Client zu senden. Wenn der Client nicht verfügbar ist, wird eine Ausnahme ausgelöst.

  7. Auf dem Client wird der Kontext in der Datei "Client.ctx" gespeichert. Die Datei wird im Verzeichnis "\bin" des Beispiels gespeichert. Wenn Sie den Client erneut öffnen, überprüft er, ob die Datei vorhanden ist. Wenn die Datei vorhanden ist, wird der gespeicherte Kontext auf den Kanal angewendet, der erstellt wird. Wenn der Workflowdienst abgeschlossen wurde und Sie den Client öffnen, während sich die Datei "Client.ctx" noch im Verzeichnis "\bin" befindet, wird versucht, den Kontext auf den Kanal anzuwenden. Dies führt zu einem Fehler, da die Workflowinstanz, mit der kommuniziert werden soll, nicht vorhanden ist. Löschen Sie die Datei, und versuchen Sie es erneut.

Senden Sie Kommentare zu diesem Thema an Microsoft.