Partager via


Duplex durable

Cette rubrique s'applique à Windows Workflow Foundation 4.

La corrélation duplex durable, également appelée corrélation de rappel, est utile lorsqu'un service de workflow a besoin d'envoyer un rappel à l'appelant initial. Contrairement au duplex WCF, le rappel peut arriver à n'importe quel moment du futur et n'est pas lié au même canal ni à la durée de vie du canal ; la seule condition est que l'appelant ait un point de terminaison actif qui écoute le message de rappel. Cela permet à deux services de workflow de communiquer dans une conversation de longue durée. Cette rubrique présente une vue d'ensemble de la corrélation duplex durable.

Utilisation de la corrélation duplex durable

Pour utiliser la corrélation duplex durable, les deux services doivent utiliser une liaison contextuelle qui prend en charge les opérations bidirectionnelles, telle que NetTcpContextBinding ou WSHttpContextBinding. Le service d'appel enregistre une propriété ClientCallbackAddress avec la liaison souhaitée sur son Endpoint client. Le service de réception reçoit ces données dans l'appel initial, puis les utilise sur son propre Endpoint dans l'activité Send qui effectue le rappel vers le service d'appel. Dans cet exemple, deux services communiquent entre eux. Le premier service appelle une méthode sur le deuxième service, puis attend une réponse. Le deuxième service connait le nom de la méthode de rappel, mais le point de terminaison du service qui implémente cette méthode n'est pas connu au moment de la conception. Dans l'exemple suivant, un service de workflow est hébergé, qui crée un Endpoint de rappel à l'aide de l'objet WSHttpContextBinding.

// Host WF Service 1.
string baseAddress1 = "https://localhost:8080/Service1";
WorkflowServiceHost host1 = new WorkflowServiceHost(GetWF1(), new Uri(baseAddress1));

// Add the callback endpoint.
WSHttpContextBinding Binding1 = new WSHttpContextBinding();
host1.AddServiceEndpoint("ICallbackItemsReady", Binding1, "ItemsReady");

// Add the service endpoint.
host1.AddServiceEndpoint("IService1", Binding1, baseAddress1);

// Open the first workflow service.
host1.Open();
Console.WriteLine("Service1 waiting at: {0}", baseAddress1);

Le workflow qui implémente ce service de workflow initialise la corrélation de rappel avec son activité Send et référence ce point de terminaison de rappel à partir de l'activité Receive en corrélation avec l'activité Send. L'exemple suivant représente le workflow retourné par la méthode GetWF1.

Variable<CorrelationHandle> CallbackHandle = new Variable<CorrelationHandle>();

Receive StartOrder = new Receive
{
    CanCreateInstance = true,
    ServiceContractName = "IService1",
    OperationName = "StartOrder"
};

Send GetItems = new Send
{
    CorrelationInitializers = 
    {
        new CallbackCorrelationInitializer
        {
            CorrelationHandle = CallbackHandle
        }
    },
    ServiceContractName = "IService2",
    OperationName = "StartItems",
    Endpoint = new Endpoint
    {
        AddressUri = new Uri("https://localhost:8081/Service2"),
        Binding = new WSHttpContextBinding
        {
            ClientCallbackAddress = new Uri("https://localhost:8080/Service1/ItemsReady")                        
        }
    }
};

Receive ItemsReady = new Receive
{
    ServiceContractName = "ICallbackItemsReady",
    OperationName = "ItemsReady",
    CorrelatesWith = CallbackHandle,
};

Activity wf = new Sequence
{
    Variables =
    {
        CallbackHandle
    },
    Activities =
    {
        StartOrder,
        new WriteLine
        {
            Text = "WF1 - Started"
        },
        GetItems,
        new WriteLine
        {
            Text = "WF1 - Request Submitted"
        },
        ItemsReady,
        new WriteLine
        {
            Text = "WF1 - Items Received"
        }
     }
};

Le deuxième service de workflow est hébergé à l'aide d'une liaison basée sur un contexte, fournie par le système.

// Host WF Service 2.
string baseAddress2 = "https://localhost:8081/Service2";
WorkflowServiceHost host2 = new WorkflowServiceHost(GetWF2(), new Uri(baseAddress2));

// Add the service endpoint.
WSHttpContextBinding Binding2 = new WSHttpContextBinding();
host2.AddServiceEndpoint("IService2", Binding2, baseAddress2);

// Open the second workflow service.
host2.Open();
Console.WriteLine("Service2 waiting at: {0}", baseAddress2);

Le workflow qui implémente ce service de workflow commence par une activité Receive. Cette activité de réception initialise la corrélation de rappel pour ce service, attend un certain temps pour simuler un travail de longue durée, puis rappelle dans le premier service à l'aide du contexte de rappel qui a été transmis lors du premier appel dans le service. L'exemple suivant représente le workflow retourné par un appel à la méthode GetWF2. Notez que l'activité Send a une adresse d'espace réservé, https://www.contoso.com ; l'adresse réelle utilisée au moment de l'exécution est l'adresse de rappel fournie.

Variable<CorrelationHandle> ItemsCallbackHandle = new Variable<CorrelationHandle>();

Receive StartItems = new Receive
{
    CorrelationInitializers = 
    {
        new CallbackCorrelationInitializer
        {
            CorrelationHandle = ItemsCallbackHandle
        }
    },
    CanCreateInstance = true,
    ServiceContractName = "IService2",
    OperationName = "StartItems"
};

Send ItemsReady = new Send
{
    CorrelatesWith = ItemsCallbackHandle,
    Endpoint = new Endpoint
    {
        // The callback address on the binding is used
        // instead of this placeholder address.
        AddressUri = new Uri("https://www.contoso.com"),

        Binding = new WSHttpContextBinding()
    },
    OperationName = "ItemsReady",
    ServiceContractName = "ICallbackItemsReady"
};

Activity wf = new Sequence
{
    Variables =
    {
        ItemsCallbackHandle
    },
    Activities =
    {
        StartItems,
        new WriteLine
        {
            Text = "WF2 - Request Received"
        },
        new Delay
        {
            Duration = TimeSpan.FromMinutes(90)
        },
        new WriteLine
        {
            Text = "WF2 - Sending items"
        },
        ItemsReady,
        new WriteLine
        {
            Text = "WF2 - Items sent"
        }
     }
};

Lorsque la méthode StartOrder est appelée sur le premier workflow, la sortie suivante s'affiche, qui indique le flux d'exécution entre les deux workflows.

Service1 waiting at: https://localhost:8080/Service1Service2 waiting at: https://localhost:8081/Service2Press enter to exit.WF1 - StartedWF2 - Request ReceivedWF1 - Request SubmittedWF2 - Sending itemsWF2 - Items sentWF1 - Items Received

Dans cet exemple, les deux workflows gèrent explicitement la corrélation à l'aide d'un objet CallbackCorrelationInitializer. Étant donné qu'il n'y avait qu'une seule corrélation dans ces exemples de workflows, la gestion CorrelationHandle par défaut aurait suffi.