Permanente DuplexkorrelationDurable Duplex Correlation

Die permanente Duplexkorrelation, die auch als Rückrufkorrelation bezeichnet wird, ist nützlich, wenn für einen Workflowdienst eine Anforderung besteht, einen Rückruf an den ursprünglichen Aufrufer zu senden.Durable duplex correlation, also known as callback correlation, is useful when a workflow service has a requirement to send a callback to the initial caller. Im Gegensatz zu WCF-Duplex kann der Rückruf jederzeit in der Zukunft geschehen und ist nicht an den gleichen Kanal bzw. die Kanallebensdauer gebunden. Die einzige Anforderung besteht darin, dass der Aufrufer über einen aktiven Endpunkt verfügt, der die Rückrufnachricht überwacht.Unlike WCF duplex, the callback can happen at any time in the future and is not tied to the same channel or the channel lifetime; the only requirement is that the caller have an active endpoint listening for the callback message. Auf diese Weise können zwei Workflowdienste eine lange Konversation führen.This allows two workflow services to communicate in a long-running conversation. Dieses Thema bietet eine Übersicht über die permanente Duplexkorrelation.This topic provides an overview of durable duplex correlation.

Verwenden der permanenten DuplexkorrelationUsing Durable Duplex Correlation

Um die permanente Duplexkorrelation zu verwenden, müssen die beiden Dienste eine kontextfähige Bindung verwenden, die bidirektionale Vorgänge unterstützt, z. B. NetTcpContextBinding oder WSHttpContextBinding.To use durable duplex correlation, the two services must use a context-enabled binding that supports two-way operations, such as NetTcpContextBinding or WSHttpContextBinding. Der aufrufende Dienst registriert eine ClientCallbackAddress mit der gewünschten Bindung auf dem Endpoint des Clients.The calling service registers a ClientCallbackAddress with the desired binding on their client Endpoint. Der empfangende Dienst empfängt diese Daten mit dem ersten Aufruf und verwendet diese dann auf seinem eigenen Endpoint in der Send-Aktivität, die den Rückruf zum aufrufenden Dienst ausführt.The receiving service receives this data in the initial call and then uses it on its own Endpoint in the Send activity that makes the call back to the calling service. In diesem Beispiel kommunizieren zwei Dienste miteinander.In this example, two services communicate with each other. Der erste Dienst ruft eine Methode auf dem zweiten Dienst auf und wartet dann auf eine Antwort.The first service invokes a method on the second service and then waits for a reply. Der zweite Dienst kennt den Namen der Rückrufmethode, aber der Endpunkt des Diensts, der diese Methode implementiert, ist zur Entwurfszeit nicht bekannt.The second service knows the name of the callback method, but the endpoint of the service that implements this method is not known at design time.

Hinweis

Permanenter Duplex kann nur verwendet werden, wenn die AddressingVersion des Endpunkts mit WSAddressing10 konfiguriert wird.Durable duplex can only be used when the AddressingVersion of the endpoint is configured with WSAddressing10. Ist dies nicht der Fall, wird eine InvalidOperationException Ausnahme wird mit der folgenden Meldung ausgelöst: "die Nachricht enthält einen rückrufkontextheader mit einem Endpunktverweis für AddressingVersion ' Addressing200408 (HYPERLINK"http://schemas.xmlsoap.org/ws/2004/08/ Adressierung"http://schemas.xmlsoap.org/ws/2004/08/addressing)'.If it is not, then an InvalidOperationException exception is thrown with the following message: "The message contains a callback context header with an endpoint reference for AddressingVersion 'Addressing200408 ( HYPERLINK "http://schemas.xmlsoap.org/ws/2004/08/addressing" http://schemas.xmlsoap.org/ws/2004/08/addressing)'. Der Rückrufkontext kann nur übertragen werden, wenn AddressingVersion mit 'WSAddressing10' konfiguriert ist."Callback context can only be transmitted when the AddressingVersion is configured with 'WSAddressing10'."

Im folgenden Beispiel wird ein Workflowdienst gehostet, der mithilfe von Endpoint einen WSHttpContextBinding für den Rückruf erstellt.In the following example, a workflow service is hosted that creates a callback Endpoint using WSHttpContextBinding.

// Host WF Service 1.  
string baseAddress1 = "http://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);  

Der Workflow, der diesen Workflowdienst implementiert, initialisiert die Rückrufkorrelation mit seiner Send-Aktivität. Er verweist in der Receive-Aktivität, die mit Send korreliert, auf diesen Rückrufendpunkt.The workflow that implements this workflow service initializes the callback correlation with its Send activity, and references this callback endpoint from the Receive activity that correlates with the Send. Im folgenden Beispiel ist der Workflow dargestellt, der von der GetWF1-Methode zurückgegeben wird.The following example represents the workflow that is returned from the GetWF1 method.

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("http://localhost:8081/Service2"),  
        Binding = new WSHttpContextBinding  
        {  
            ClientCallbackAddress = new Uri("http://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"  
        }  
     }  
};  

Der zweite Workflowdienst wird mit einer vom System bereitgestellten, kontextbasierten Bindung gehostet.The second workflow service is hosted using a system-provided, context-based binding.

// Host WF Service 2.  
string baseAddress2 = "http://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);  

Der Workflow, der diesen Workflowdienst implementiert, beginnt mit einer Receive-Aktivität.The workflow that implements this workflow service begins with a Receive activity. Diese Empfangsaktivität initialisiert die Rückrufkorrelation für diesen Dienst, verwendet eine Verzögerung als Simulation eines längeren Arbeitsvorgangs und führt dann den Rückruf an den ersten Dienst aus. Dafür wird der Rückrufkontext verwendet, der beim ersten Aufruf an den Dienst übergeben wurde.This receive activity initializes the callback correlation for this service, delays for a period of time to simulate long-running work, and then calls back into the first service using the callback context that was passed in the first call into the service. Im folgenden Beispiel ist der Workflow dargestellt, der bei einem Aufruf der GetWF2-Methode zurückgegeben wird.The following example represents the workflow that is returned from a call to GetWF2. Beachten Sie, dass die Send-Aktivität über die Platzhalteradresse http://www.contoso.com verfügt. Die zur Laufzeit verwendete tatsächliche Adresse ist die angegebene Rückrufadresse.Note that the Send activity has a placeholder address of http://www.contoso.com; the actual address used at runtime is the supplied callback address.

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("http://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"  
        }  
     }  
};  

Wenn die StartOrder-Methode für den ersten Workflow aufgerufen wird, wird die folgende Ausgabe angezeigt. Die Ausgabe verdeutlicht den Ausführungsfluss durch die beiden Workflows.When the StartOrder method is invoked on the first workflow, the following output is displayed, which shows the flow of execution through the two workflows.

Service1 waiting at: http://localhost:8080/Service1  
Service2 waiting at: http://localhost:8081/Service2  
Press enter to exit.   
WF1 - Started  
WF2 - Request Received  
WF1 - Request Submitted  
WF2 - Sending items  
WF2 - Items sent  
WF1 - Items Received  

In diesem Beispiel verwalten beide Workflows die Korrelation explizit mithilfe eines CallbackCorrelationInitializer-Objekts.In this example, both workflows explicitly manage correlation using a CallbackCorrelationInitializer. Da in diesen Beispielworkflows nur eine einzelne Korrelation vorhanden war, reicht die CorrelationHandle-Standardverwaltung in diesem Fall aus.Because there was only a single correlation in these sample workflows, the default CorrelationHandle management would have been sufficient.

Siehe auchSee Also

Permanenter Duplex [ WF-Beispiele ]Durable Duplex [WF Samples]