Condividi tramite


Esempio di servizio del flusso di lavoro duplex

In questo esempio viene illustrato come eseguire una comunicazione duplex asincrona tra due servizi comunicanti. Nell'esempio viene inoltre illustrato come eseguire una comunicazione localhost-a-flusso di lavoro utilizzando i messaggi. Durante l'esecuzione della comunicazione duplex tra due servizi, i due servizi devono scambiarsi un contesto prima che la comunicazione possa verificarsi in entrambi le direzioni. Il servizio che avvia la comunicazione riceve il contesto nella risposta al messaggio. Per supportare la comunicazione dal servizio ricevente al servizio mittente, quest'ultimo deve inviare le informazioni relative al contesto nel primo messaggio.

Nota

Per poter essere generato ed eseguito, l'esempio richiede che sia installato .NET Framework versione 3.5. Per aprire il progetto e i file della soluzione è necessario Visual Studio 2008.

Per ulteriori informazioni sulla configurazione di questo esempio, vedere One-time Setup Procedure for Windows Communication Foundation Samples.

I messaggi vengono inoltre utilizzati per la comunicazione tra il localhost e il servizio. Il localhost espone un endpoint conosciuto che il servizio può utilizzare per il callback. Questo esempio implementa un tipo di LocalWorkflowServiceHost che fornisce la funzionalità per creare il listener locale così come l'host del servizio del flusso di lavoro del servizio ospitato.

Architettura di esempio del servizio del flusso di lavoro duplex

Questo esempio comprende le entità di comunicazione seguenti:

  • Host del client
    L'host del client comunica con il flusso di lavoro del client chiamando operazioni in IReverseContract. Il flusso di lavoro del client viene creato quando l'host del client chiama l'operazione BeginWork. In risposta all'operazione BeginWork, il flusso di lavoro del client restituisce un messaggio che include il contesto per il flusso di lavoro del client. Il canale creato dall'host per comunicare con il flusso di lavoro del client è ora dotato del contesto per ulteriori comunicazioni. In questo esempio viene illustrato come l'host del client utilizzi lo stesso canale per inviare più elementi di lavoro al flusso di lavoro del client.
    L'host del client è dotato di un endpoint di ascolto noto, in modo che il flusso di lavoro possa comunicare con l'host del client. In questo esempio, l'endpoint noto si chiama HostEndPoint. L'LocalWorkflowServiceHost viene utilizzato per creare l'endpoint noto per l'host del client così come l'host del servizio del flusso di lavoro per il flusso di lavoro del client.

    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();
    
  • Flusso di lavoro del client (esposto come un servizio)
    Il flusso di lavoro del client implementa IReverseContract. Il flusso di lavoro del servizio utilizza questo elemento, come illustrato precedente, per comunicare con il flusso di lavoro del client. Il flusso di lavoro del client chiama l'operazione BeginWorkflow che crea il flusso di lavoro del servizio. La risposta restituisce il contesto per il flusso di lavoro del servizio, utilizzato nelle successive comunicazioni del flusso di lavoro del client al flusso di lavoro del servizio. Come parte dell'operazione BeginWorkflow, il flusso di lavoro del client passa il proprio riferimento all'endpoint che contiene l'indirizzo endpoint e le intestazioni del contesto del flusso di lavoro del servizio. Il flusso di lavoro del servizio utilizza questo indirizzo endpoint per comunicare in modo asincrono con il flusso di lavoro del client.
    Il gestore eventi WaitForBeginWork nello stato iniziale implementa un'attività di codice denominata DoSetReturnAddress. Questa attività imposta il riferimento all'endpoint che viene inviato al flusso di lavoro del servizio, come illustrato nell'esempio seguente.

    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>());
    }
    
  • Host del servizio
    Questo esempio implementa un host del servizio del flusso di lavoro. Apre un listener che ascolta le richieste del client. La prima richiesta del client crea un'istanza del flusso di lavoro servizio. Tutte le richieste successive vengono indirizzate alla stessa istanza del flusso di lavoro, visto che le richieste portano il contesto nell'intestazione del messaggio.

  • Flusso di lavoro del servizio (esposto come un servizio)
    Il flusso di lavoro del servizio implementa IForwardContract. Il flusso di lavoro del servizio riceve il riferimento all'endpoint per il flusso di lavoro del client nell'operazione BeginWorkflow . Il flusso di lavoro del servizio applica questo riferimento all'endpoint all'attività Send che invia un messaggio in modo asincrono al flusso di lavoro del client. Il gestore eventi WaitForBeginWorkflow fornisce l'attività Receive BeginWorkflow. Nell'attività Receive esiste un'attività di codice denominata ApplyReturnAddress che utilizza l'indirizzo del mittente nell'attività Send per inviare un messaggio al flusso di lavoro del client, come illustrato nel codice seguente.

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

    La classe LocalWorkflowServiceHost crea l'infrastruttura necessaria per la comunicazione da host-a-flusso di lavoro. Il servizio del flusso di lavoro locale esegue due attività principali:

    • Crea un listener locale in modo che l'host possa ascoltare messaggi dal flusso di lavoro.
    • Crea un'istanza WorkflowServiceHost per creare un listener per il flusso di lavoro.

    La classe fornisce inoltre funzioni di supporto in modo che l'host possa gestire il contesto utilizzato per comunicare con il flusso di lavoro. Se l'host viene riciclato, questo contesto viene utilizzato per comunicare con l'istanza del flusso di lavoro.

Il progetto WorkflowServiceUtility fornisce tutte le funzioni di supporto necessarie per modificare il contesto. Fornisce funzioni per estrarre il contesto dal canale, applicare il contesto a un canale e applicare un indirizzo endpoint all'attività Send.

Per impostare, compilare ed eseguire l'esempio

  1. Per installare i provider di persistenza, eseguire lo script CreateStores.cmd situato nell'argomento One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. Scaricare Utilità di servizio del flusso di lavoro e salvarlo in modo che le cartelle DuplexWorkflowService e WorkflowServiceUtility si trovino nella stessa cartella padre.

  3. Se non si vuole utilizzare i provider di persistenza, impostare la sezione <WorkflowRuntime> dei file App.config come commento.

  4. Questo esempio utilizza due database di persistenza. Il flusso di lavoro del servizio utilizza NetFx35Samples_ServiceWorkflowStore e il client utilizza NetFx35Samples_ClientWorkflowStore. È possibile creare questi archivi in SQL Server o SQL Server Express. Le stringhe di connessione correnti situate nei file App.config presuppongono che si utilizzi SQL Server Express. Se gli archivi vengono creati in SQL Server, assicurarsi di modificare le stringhe di connessione nei file App.config.

  5. Con l'host del client e l'host del servizio in esecuzione, selezionare S nella finestra della console per elaborare gli elementi di lavoro. È possibile inviare più elementi di lavoro per l'elaborazione. Se si interrompe e riavvia il client, l'elaborazione riprende da dove è stata interrotta.

  6. Per testare la natura durevole dei servizi, chiudere le applicazioni client e del servizio, quindi riavviare prima l'applicazione client e poi l'applicazione del servizio. Questa operazione è utile per l'ordinamento in sequenza, visto che quando si esegue il flusso di lavoro del servizio, questo tenta di restituire messaggi al client. Se il client non è disponibile, si riceve un'eccezione.

  7. Il contesto viene archiviato nel file Client.ctx nel client. Il file viene archiviato nella directory \bin dell'esempio. Quando viene riavviato, il client controlla se il file è presente. Se il file è presente, applica il contesto archiviato al canale che viene creato. Se il servizio del flusso di lavoro è completato e si apre il client con il file Client.ctx ancora nella directory \bin, il servizio tenterà di applicare il contesto al canale. Questa operazione genera un errore, perché l'istanza del flusso di lavoro con la quale si desidera comunicare non è presente. Eliminare il file e provare nuovamente.

Invia commenti su questo argomento a Microsoft.