永久性雙工相互關聯
永久性雙工相互關聯也稱為回呼相互關聯,在工作流程服務需要傳送回呼至初始呼叫端時相當實用。 不同於 WCF 雙工,回呼未來隨時都可能發生,而且不會繫結至相同的通道或通道存留期。 唯一的需求是呼叫端具有接聽回呼訊息的作用中端點。 如此可讓兩項工作流程服務在長時間執行的對話中彼此通訊。 本文提供永久性雙工相互關聯的概觀。
使用永久性雙工相互關聯
若要使用永久性雙工相互關聯,兩項服務必須使用支援雙向作業的啟用內容繫結,例如 NetTcpContextBinding 或 WSHttpContextBinding。 呼叫服務會將 ClientCallbackAddress 註冊至其用戶端 Endpoint 上所需的繫結。 接收服務會在初始呼叫中接收這項資料,然後在對呼叫服務進行回呼的 Endpoint 活動中,於自己的 Send 上使用該資料。 在這個範例中,兩項服務會彼此通訊。 第一項服務會在第二項服務上叫用方法,然後等候回覆。 第二項服務知道回呼方法的名稱,但是在設計階段並不知道實作這個方法的服務端點。
注意
只有當端點的 AddressingVersion 是使用 WSAddressing10 來設定時,才能使用永久性雙工。 否則會擲回 InvalidOperationException 例外狀況,並顯示下列訊息:「訊息包含的回呼內容標頭具有 AddressingVersion 的端點參考。 只有當 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 管理就已經足夠。