Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dauerhafte Duplexkorrelation, auch bekannt als Rückrufkorrelation, ist nützlich, wenn ein Workflowdienst eine Anforderung zum Senden eines Rückrufs an den ersten Aufrufer hat. Im Gegensatz zu WCF Duplex kann der Rückruf jederzeit in Der Zukunft erfolgen und ist nicht an denselben Kanal oder die Kanallebensdauer gebunden. Die einzige Anforderung besteht darin, dass der Anrufer über einen aktiven Endpunkt verfügt, der auf die Rückrufnachricht lauscht. Auf diese Weise können zwei Workflowdienste in einem lang anhaltenden Gespräch kommunizieren. Dieser Artikel enthält eine Übersicht über die dauerhafte Duplexkorrelation.
Verwenden der permanenten Duplexkorrelation
Um eine dauerhafte Duplexkorrelation zu verwenden, müssen die beiden Dienste eine kontextfähige Bindung verwenden, die bidirektionale Vorgänge unterstützt, wie NetTcpContextBinding oder WSHttpContextBinding. Der aufrufende Dienst registriert eine ClientCallbackAddress mit der gewünschten Bindung auf dem Endpoint des Clients. Der empfangende Dienst empfängt diese Daten im ersten Aufruf und verwendet sie dann eigenständig Endpoint in der Send Aktivität, die den Aufruf an den aufrufenden Dienst zurückgibt. In diesem Beispiel kommunizieren zwei Dienste miteinander. Der erste Dienst ruft eine Methode für den zweiten Dienst auf und wartet dann auf eine Antwort. Der zweite Dienst kennt den Namen der Rückrufmethode, aber der Endpunkt des Diensts, der diese Methode implementiert, ist zur Entwurfszeit nicht bekannt.
Hinweis
Dauerhafter Duplex kann nur verwendet werden, wenn der AddressingVersion Endpunkt mit WSAddressing10konfiguriert ist. Andernfalls wird eine InvalidOperationException-Ausnahme mit der folgenden Meldung ausgelöst: „Die Nachricht enthält einen Rückrufkontextheader mit einem Endpunktverweis für AddressingVersion. Der Rückrufkontext kann nur übertragen werden, wenn die AddressingVersion mit 'WSAddressing10' konfiguriert ist."
Im folgenden Beispiel wird ein Workflowdienst gehostet, der mithilfe von Endpoint einen WSHttpContextBinding für den Rückruf erstellt.
// 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 und verweist auf diesen Rückrufendpunkt aus der Receive Aktivität, die mit der SendAktivität korreliert. Das folgende Beispiel stellt den Workflow dar, der von der GetWF1 Methode zurückgegeben wird.
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 mithilfe einer vom System bereitgestellten kontextbasierten Bindung gehostet.
// 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. Diese Empfangsaktivität initialisiert die Rückrufkorrelation für diesen Dienst, verzögert sich über einen bestimmten Zeitraum, um lang laufende Arbeit zu simulieren, und ruft dann unter Verwendung des Rückrufkontexts, der beim ersten Anruf an den Dienst übergeben wurde, in den ersten Dienst zurück. Das folgende Beispiel stellt den Workflow dar, der von einem Aufruf an GetWF2zurückgegeben wird. Die Send Aktivität hat eine Platzhalteradresse von http://www.contoso.com; die tatsächliche Adresse, die zur Laufzeit verwendet wird, ist die angegebene Rückrufadresse.
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 im ersten Workflow aufgerufen wird, wird die folgende Ausgabe angezeigt, die den Ausführungsfluss über die beiden Workflows anzeigt.
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 einer CallbackCorrelationInitializer. Da in diesen Beispielworkflows nur eine einzige Korrelation vorhanden war, wäre die Standardverwaltung CorrelationHandle ausreichend gewesen.