永久性雙工
本主題僅適用於 Windows Workflow Foundation 4。
永久性雙工相互關聯也稱為回呼相互關聯,在工作流程服務需要傳送回呼至初始呼叫端時相當實用。與 WCF 雙工不同的是,回呼可以在未來隨時進行,並且不受限於相同通道或通道存留期;唯一的需求是呼叫端擁有主動端點,可接聽回呼訊息。如此可讓兩項工作流程服務在長時間執行的對話中彼此通訊。本主題提供永久性雙工相互關聯的概觀。
使用永久性雙工相互關聯
若要使用永久性雙工相互關聯,兩項服務必須使用支援雙向作業的啟用內容繫結,例如 NetTcpContextBinding 或 WSHttpContextBinding。呼叫服務會將 ClientCallbackAddress 註冊至其用戶端 Endpoint 上所需的繫結。接收服務會在初始呼叫中接收這項資料,然後在對呼叫服務進行回呼的 Send 活動中,於自己的 Endpoint 上使用該資料。在這個範例中,兩項服務會彼此通訊。第一項服務會在第二項服務上叫用方法,然後等候回覆。第二項服務知道回呼方法的名稱,但是在設計階段並不知道實作這個方法的服務端點。下列範例會裝載工作流程服務,以使用 WSHttpContextBinding 建立回呼 Endpoint。
// 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);
實作此工作流程服務的工作流程會使用其 Send 活動初始化回呼相互關聯,並且從與 Send 相互關聯的 Receive 活動參考此回呼端點。下列範例表示自 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"
}
}
};
第二項工作流程服務是使用系統提供之以內容為主的繫結進行裝載。
// 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);
實作此工作流程服務的工作流程會以 Receive 活動開始執行。此接收活動會初始化此服務的回呼相互關聯,延遲一段時間以模擬長時間執行的工作,然後使用第一次服務呼叫中傳遞的回呼內容來回呼第一項服務。下列範例表示自 GetWF2
的呼叫傳回的工作流程。請注意,Send 活動有預留位置位址 https://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("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"
}
}
};
在第一個工作流程上叫用 StartOrder
方法時,會顯示下列輸出,其中顯示兩個工作流程之間執行的流向。
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
在這個範例中,兩個工作流程都會使用 CallbackCorrelationInitializer 明確管理相互關聯。由於上述這些範例工作流程中只有單一相互關聯,因此預設的 CorrelationHandle 管理就已經足夠。