Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Устойчивая дуплексная корреляция, также известная как корреляция обратного вызова, полезна, если служба рабочего процесса имеет требование отправить обратный вызов исходному вызывающому объекту. В отличие от дуплексного WCF, обратный вызов может произойти в любой момент в будущем и не привязан к одному каналу или времени существования канала. Единственное требование заключается в том, что вызывающий должен иметь активную конечную точку соединения, прослушивающую сообщение обратного вызова. Это позволяет двум службам рабочих процессов взаимодействовать в длительной беседе. В этой статье представлен обзор устойчивой дуплексной корреляции.
Использование устойчивой дуплексной корреляции
Чтобы использовать устойчивую дуплексную корреляцию, две службы должны использовать привязку с поддержкой контекста, которая поддерживает двустороннюю операцию, например NetTcpContextBinding или WSHttpContextBinding. Вызывающая служба регистрирует ClientCallbackAddress с желаемой привязкой на их клиенте Endpoint. Получающая служба получает эти данные в первоначальном вызове, а затем использует их самостоятельно Endpoint в Send активности, которая возвращает обратный вызов вызывающей службе. В этом примере две службы взаимодействуют друг с другом. Первая служба вызывает метод во второй службе, а затем ожидает ответа. Вторая служба знает имя метода обратного вызова, но конечная точка службы, реализующая этот метод, не известна во время разработки.
Замечание
Устойчивый дуплекс можно использовать только в случае, если AddressingVersion конечной точки настроен с помощью WSAddressing10. Если это не так, InvalidOperationException исключение создается со следующим сообщением: "Сообщение содержит заголовок контекста обратного вызова с ссылкой на конечную точку для AddressingVersion. Контекст обратного вызова может передаваться только когда версия адресации настроена как 'WSAddressing10'.
В следующем примере размещается служба рабочего процесса, которая создает обратный вызов Endpoint с помощью 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);
Рабочий процесс, реализующий эту службу обработки, инициализирует корреляцию обратного вызова со своей Send активностью и ссылается на эту конечную точку обратного вызова из Receive активности, которая коррелирует с Send. В следующем примере представлен рабочий процесс, возвращаемый из 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("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"
}
}
};
Вторая служба рабочего процесса размещена с использованием предоставляемой системой привязки, основанной на контексте.
// 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);
Рабочий процесс, реализующий эту службу рабочего процесса, начинается с Receive активности. Это действие инициализирует корреляцию обратного вызова для этой службы, задерживается на определенное время для имитации длительной работы, а затем снова вызывает первую службу с использованием контекста обратного вызова, который был передан при первом вызове в службу. В следующем примере представлен рабочий процесс, возвращаемый из вызова GetWF2
. Действие Send имеет плэйсхолдер для адреса http://www.contoso.com
; реальный адрес, используемый при выполнении, — это предоставленный адрес обратного вызова.
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"
}
}
};
StartOrder
При вызове метода в первом рабочем процессе отображаются следующие выходные данные, показывающие поток выполнения с помощью двух рабочих процессов.
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
В этом примере оба рабочего процесса явно управляют корреляцией с помощью .CallbackCorrelationInitializer Так как в этих примерах рабочих процессов существовала только одна корреляция, управление по умолчанию CorrelationHandle было бы достаточно.