SynchronizationContext(.NET 2.0 引入)定義於 System.Threading,核心成員:
public delegate void SendOrPostCallback(object state);
public class SynchronizationContext
{
public virtual void Post(SendOrPostCallback callback, object state); // 非同步
public virtual void Send(SendOrPostCallback callback, object state); // 同步
public static void SetSynchronizationContext(SynchronizationContext context);
public static SynchronizationContext Current { get; }
}
儲存於執行緒區域儲存區 (TLS),每個執行緒可有一個同步內容。用途:在呼叫執行緒與目標執行緒間封送方法呼叫。
Windows Forms / WPF 中,只有建立視窗的 UI 執行緒能更新介面。WindowsFormsSynchronizationContext 將委派轉為 Windows 訊息發送到 UI 訊息佇列,BackgroundWorker 即建構於此機制之上。
ServiceBehaviorAttribute.UseSynchronizationContext 預設 trueServiceHost 的執行緒有同步內容,WCF 自動將所有呼叫封送至該內容static void Main()
{
Form form = new MyForm(); // 此處建立同步內容
ServiceHost host = new ServiceHost(typeof(MyService));
host.Open();
Application.Run(form); // UI 訊息迴圈
host.Close();
}
若 host.Open() 在建立 Form 之前,則無法受益於自動關聯。
將所有呼叫封送至自訂執行緒池,控制併發數量、最大化吞吐量。
SynchronizationContext,實作 Post/Send 佇列至執行緒池IContractBehavior.ApplyDispatchBehavior 將同步內容指派給 DispatchRuntime.SynchronizationContextIServiceBehavior.Validate 訂閱 ServiceHostBase.Closed 事件釋放執行緒池ThreadPoolHelper 字典對應服務型別到同步器實例,確保多端點共用同一池[ThreadPoolBehavior(3, typeof(MyService))]
class MyService : IMyContract { ... }
池大小 = 1 時,建立特定執行緒與所有服務呼叫的親和關係。適用場景:
此時所有服務實例天然執行緒安全,建議搭配 ConcurrencyMode.Single。
[ThreadAffinityBehavior(typeof(MyService))]
class MyService : IMyContract { ... }
預設先進先出。PrioritySynchronizer 依優先權排序佇列:
public enum CallPriority { Low, Normal, High }
public class PrioritySynchronizer : ThreadPoolSynchronizer
{
public static CallPriority Priority { get; set; } // TLS 儲存
}
WCF 客戶端執行緒不直接呼叫服務,無法用 TLS。解決方案:訊息標頭帶外傳遞。
[DataContract]
public class GenericContext
{
[DataMember] public readonly T Value;
public static GenericContext Current
{
get => OperationContext.Current.IncomingMessageHeaders.GetHeader>(...);
set => OperationContext.Current.OutgoingMessageHeaders.Add(...);
}
}
public abstract class HeaderClientBase : ClientBase where T : class
{
protected H Header;
protected virtual object Invoke(string operation, params object[] args)
{
using (new OperationContextScope(InnerChannel))
{
GenericContext.Current = new GenericContext(Header);
return typeof(T).GetMethod(operation).Invoke(Channel, args);
}
}
}
public abstract class PriorityClientBase : HeaderClientBase where T : class
{
public PriorityClientBase(CallPriority priority) : base(priority) { }
}
class MyContractClient : PriorityClientBase, IMyContract
{
public MyContractClient(CallPriority priority) : base(priority) { }
public void MyMethod(string text) => Invoke("MyMethod", text);
}
var proxy = new MyContractClient(CallPriority.High);
proxy.MyMethod();
CallbackBehaviorAttribute.UseSynchronizationContext 同樣支援自訂同步內容。關鍵差異:
IEndpointBehavior.ApplyClientBehavior 設定 ClientRuntime.CallbackDispatchRuntime.SynchronizationContextAppDomain.CurrentDomain.ProcessExit[CallbackThreadAffinityBehavior(typeof(MyClient))]
class MyClient : IMyContractCallback, IDisposable { ... }
GenericContext<T> 技術適用於任何需帶外參數的 WCF 擴展同步內容與 WCF 結合,產生出色且高效的程式模型。本文展示的自訂標頭與通用內容技術,在整個 WCF 程式設計領域極具價值。