會話是兩個端點之間傳送的所有訊息相互關聯。 實例化 是指控制使用者定義服務物件的存留期及其相關 InstanceContext 物件。 併發 是指在相同環境中同時控制多個執行緒的詞。
本主題描述這些設定、如何使用這些設定,以及它們之間的各種互動。
會議
當服務合約將 ServiceContractAttribute.SessionMode 屬性設定為 SessionMode.Required時,該合約表示所有呼叫(也就是支援呼叫的基礎訊息交換)都必須是相同交談的一部分。 如果合約規定允許會話但不要求必須建立會話,則客戶可以連線並選擇建立或不建立會話。 如果會話結束,並且在相同的會話型通道上傳送訊息時,將會擲回例外狀況。
WCF 會話具有以下主要概念性功能:
呼叫端應用程式會明確起始和終止它們。
會話期間傳遞的訊息會依照接收的順序進行處理。
會話會將一組訊息整合成一個交談。 該相互關聯的意義是抽象概念。 例如,一個會話型通道可能會根據共用網路連線將訊息相互關聯,而另一個會話型通道可能會根據訊息本文中的共用標記來關聯訊息。 可以從會話衍生的功能取決於相互關聯的性質。
沒有與 WCF 會話相關聯的一般數據存放區。
如果您熟悉 ASP.NET 應用程式中的 System.Web.SessionState.HttpSessionState 類別及其提供的功能,您可能會注意到該會話類型與 WCF 會話之間的下列差異:
ASP.NET 工作階段始終由伺服器起始。
ASP.NET 工作階段是隱含地未經排序。
ASP.NET 工作階段會提供一個跨要求的通用資料儲存機制。
用戶端應用程式和服務應用程式會以不同方式與會話互動。 用戶端應用程式會起始會話,然後接收並處理會話內傳送的訊息。 服務應用程式可以使用會話作為擴充點來新增其他行為。 這可透過直接使用 InstanceContext 或實作自定義實例內容提供者來完成。
實體化
使用ServiceBehaviorAttribute.InstanceContextMode屬性設定的實例行為控制 InstanceContext 如何在回應傳入訊息時建立。 根據預設,每個物件 InstanceContext 都會與一個使用者定義的服務對象相關聯,因此設定 InstanceContextMode 屬性也會控制使用者定義服務對象的實例。 列舉 InstanceContextMode 會定義實例模式。
下列實例模式可供使用:
PerCall:對每個用戶端要求都會建立一個新的 InstanceContext,因此每次請求都會創建一個服務物件。
PerSession:系統會為每個新的用戶端會話建立新的 InstanceContext(因此服務物件),並在該會話的整個存續期間進行維護(這需要支持會話的綁定)。
Single:一個單一的InstanceContext(因此服務物件)會處理應用程式生命週期內的所有客戶端請求。
下列程式代碼範例示範在服務類別上明確設定的預設值InstanceContextModePerSession。
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorInstance
{
...
}
當 ServiceBehaviorAttribute.InstanceContextMode 屬性控制 InstanceContext 的釋放頻率時,OperationBehaviorAttribute.ReleaseInstanceMode 和 ServiceBehaviorAttribute.ReleaseServiceInstanceOnTransactionComplete 屬性則控制服務對象釋放的時間。
Well-Known 單例服務
單一實例服務物件的一個變化有時很有用:您可以自行建立服務物件,並使用該物件建立服務主機。 若要這樣做,您也必須將 ServiceBehaviorAttribute.InstanceContextMode 屬性設定為 Single,否則在開啟服務主機時將擲回例外狀況。
使用ServiceHost(Object, Uri[])構造函式來建立這類服務。 當您想要提供特定物件實例供單一服務使用時,它會提供實作自定義 System.ServiceModel.Dispatcher.IInstanceContextInitializer 的替代方案。 當您的服務實作類型難以建構時,您可以使用這個多載(例如,如果它未實作無參數公用建構函式)。
請注意,當物件提供給這個建構函式時,與 Windows Communication Foundation (WCF) 實例行為相關的某些功能會以不同的方式運作。 例如,當提供單例物件實例時,調用 InstanceContext.ReleaseServiceInstance 沒有任何作用。 同樣地,會忽略任何其他實例發行機制。 始終會像是將 ServiceHost 屬性在所有操作中設定為 OperationBehaviorAttribute.ReleaseInstanceMode 。
共用 InstanceContext 物件
您也可以自行執行該關聯,來控制哪個會話通道或呼叫與哪個 InstanceContext 對象相關聯。
並行性
併發是控制 InstanceContext 在任意時間活躍線程數量的過程。 這是透過使用 ServiceBehaviorAttribute.ConcurrencyMode 和 ConcurrencyMode 列舉來進行控制。
下列三種並行模式可供使用:
Single:每個實例內容一次最多可以有一個線程處理實例內容中的訊息。 想要使用相同的實例內容的其他線程必須封鎖,直到原始線程結束實例內容為止。
Multiple:每個服務實例可以有多個線程同時處理訊息。 服務實作必須是線程安全,才能使用此併發模式。
Reentrant:每個服務實例一次只處理一則訊息,並且可以接受可重入操作呼叫。 服務只會在透過 WCF 用戶端物件呼叫時接受這些呼叫。
備註
理解和開發能安全使用多個執行緒的程式碼可能很難成功撰寫。 使用 Multiple 或 Reentrant 值之前,請確定您的服務已針對這些模式正確設計。 如需詳細資訊,請參閱ConcurrencyMode。
並行存取的使用與實例模式相關。 在 PerCall 實例化中,並行性並不相關,因為每個訊息都是由新的 InstanceContext 處理,因此 InstanceContext 中絕不會有超過一個線程是活躍的。
下列程式代碼範例示範如何將 ConcurrencyMode 屬性設定為 Multiple。
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class CalculatorService : ICalculatorConcurrency
{
...
}
會話與 InstanceContext 設定互動
會話和 InstanceContext 的互動取決於合約中的列舉型別的值 SessionMode 的組合,以及服務實作中的屬性 ServiceBehaviorAttribute.InstanceContextMode,這控制了通道與特定服務對象之間的關聯。
下表顯示在服務結合ServiceContractAttribute.SessionMode屬性和ServiceBehaviorAttribute.InstanceContextMode屬性值時,傳入通道支援或不支援會話的結果。
InstanceContextMode 值 | Required | Allowed | NotAllowed |
---|---|---|---|
PerCall | - 具備會話通道的行為:每次呼叫都會產生一個會話和 InstanceContext。 - 無會話通道的情況:會拋出例外狀況。 |
- 具備會話通道的行為:每次呼叫都會產生一個會話和 InstanceContext。 - 無工作階段信道的行為:每個呼叫都有 InstanceContext。 |
- 具有會話通道的行為:拋出例外狀況。 - 無工作階段信道的行為:每個呼叫都有 InstanceContext。 |
PerSession | - 具有會話通道的行為:每個通道都有一個會話和 InstanceContext。 - 無會話通道的情況:會拋出例外狀況。 |
- 具有會話通道的行為:每個通道都有一個會話和 InstanceContext。 - 無工作階段信道的行為:每個呼叫都有 InstanceContext。 |
- 具有會話通道的行為:拋出例外狀況。 - 無工作階段信道的行為:每個呼叫都有 InstanceContext。 |
單身 | - 具有會話通道的特性:會話和一個 InstanceContext 應用於所有呼叫。 - 無會話通道的情況:會拋出例外狀況。 |
- 具有會話通道的行為:一個會話,以及針對已建立或使用者指定的單一實例的InstanceContext。 使用無會話通道的行為:針對已建立或使用者指定的單一實例InstanceContext。 |
- 具有會話通道的行為:拋出例外狀況。 - 使用無工作階段信道的行為:InstanceContext 用於每個已建立的單一實例或使用者指定的單一實例。 |