首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 從理論到實踐 (8):雙工事件廣播實戰解析

     編輯:關於.NET

文章導讀

本文結合分散式任務管理系統實例,深入解析 WCF 雙工通訊實現事件廣播的核心技術難點:ConcurrencyMode 設定、PerSession 實例下的廣播機制、會話維護陷阱、非同步處理策略。適合具備 WCF 訊息交換模式基礎的進階學習者。

核心知識點

  • 雙工事件廣播系統架構設計
  • ConcurrencyMode 與單向回調的關鍵配置
  • PerSession 模式下靜態事件實現跨實例廣播
  • IsInitiating/IsTerminating 解決會話過期難題
  • 服務端/客戶端非同步處理最佳實踐

一、系統需求與架構設計

功能清單:

  1. 客戶端 Accept() 連線並保持會話
  2. 啟動時 GetJobs() 獲取任務列表
  3. AddJob() 新增任務 → 服務端廣播「新增完成」事件
  4. 客戶端命令 Do(jobName) 執行任務 → 服務端廣播「開始/結束」事件
  5. 所有廣播與任務執行採用非同步,不阻塞服務執行緒

專案結構:

專案職責
Jillzhang.Event.Core定義服務合約 (IServer)、回調合約 (ICallback)、資料合約 (Job)
Jillzhang.Event.Service服務實作,含廣播邏輯
Jillzhang.Event.HostConsole 宿主
Jillzhang.Event.Client / Client2雙客戶端驗證廣播

最終運行效果圖

二、核心技術難點深度解析

1. ConcurrencyMode 與回調模式的黃金搭配

問題:預設 ConcurrencyMode.Single 單執行緒處理請求。若回調非單向,服務端會阻塞等待客戶端回應,極易死鎖或超時。

兩種解決方案:

方案設定優缺點
回調設為 One-Way(推薦) [OperationContract(IsOneWay=true)] + ConcurrencyMode.Single 單執行緒安全、無阻塞、效能佳。經測試可完美支援雙工。
多執行緒模式 ConcurrencyMode.Multiple 允許同步回調,但需自行處理執行緒安全,複雜度高。

避坑:ConcurrencyMode.Reentrant 雖允許單執行緒重入,但不保證事務完整性,生產環境慎用。

2. PerSession 實例如何實現廣播?

挑戰:PerSession 每個會話對應一個服務實例,廣播需遍歷所有會話實例發送回調。

巧解:靜態事件 + 委派清單

// 服務類別定義靜態事件
public static event ServerEventHandler OnStatusChanged;

// 每個實例建構時訂閱
public Server() {
    OnStatusChanged += InstanceHandler;
}

// 廣播實作
private void BroadcastEvent(CallbackEventArg e, ServerEventHandler temp) {
    if (OnStatusChanged != null) {
        foreach (ServerEventHandler handler in temp.GetInvocationList()) {
            // 非同步發送,避免單一客戶端阻塞廣播
            handler.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
        }
    }
}

關鍵點:GetInvocationList() 取得所有訂閱者委派,逐一 BeginInvoke 非同步發送。

3. 會話過期陷阱與 IsInitiating/IsTerminating 破解

現象:回調前幾次正常,隨後失效。根因:Accept() 後未及時呼叫業務方法,會話閒置逾時中斷。

解決:在服務合約明確標註操作角色:

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallback))]
public interface IServer {
    // 啟動操作:IsInitiating=true, IsTerminating=false
    [OperationContract(IsOneWay = true, IsInitiating = true, IsTerminating = false)]
    void Accept();

    // 一般操作:不啟動不終結會話
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void Do(string jobName);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void AddJob(Job job);

    // 查詢操作:雙向,但不影響會話狀態
    [OperationContract(IsOneWay = false, IsInitiating = false, IsTerminating = false)]
    List<Job> GetJobs();
}

核心邏輯:IsTerminating=false 確保操作完成後會話持續存活,防止閒置逾時自動斷開。

4. 非同步處理策略

層面技術選型實作要點
服務端事件廣播 委派 BeginInvoke/EndInvoke 參考 BroadcastEvent 實作,非同步發送避免阻塞
客戶端耗時操作 BackgroundWorker UI 執行緒安全回報進度/結果,支援取消
任務執行 獨立執行緒/執行緒池 服務端 Do() 內啟動背景執行緒執行任務,主執行緒立即返回

三、合約定義完整程式碼

// ICallback.cs - 客戶端需實作
[ServiceContract]
public interface ICallback {
    [OperationContract(IsOneWay = true)]
    void OnJobAdded(Job job);
    [OperationContract(IsOneWay = true)]
    void OnJobStarted(string jobName);
    [OperationContract(IsOneWay = true)]
    void OnJobCompleted(string jobName, bool success);
}

// IServer.cs - 服務端合約
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallback))]
public interface IServer {
    [OperationContract(IsOneWay = true, IsInitiating = true, IsTerminating = false)]
    void Accept();
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void Do(string jobName);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void AddJob(Job job);
    [OperationContract(IsOneWay = false, IsInitiating = false, IsTerminating = false)]
    List<Job> GetJobs();
}

四、服務實作關鍵片段

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class Server : IServer {
    // 靜態事件實現跨實例廣播
    public static event ServerEventHandler OnStatusChanged;

    public Server() {
        OnStatusChanged += InstanceHandler;
    }

    public void Accept() { /* 會話建立,無邏輯 */ }

    public void AddJob(Job job) {
        // 業務邏輯...
        BroadcastEvent(new CallbackEventArg(JobEventType.Added, job), OnStatusChanged);
    }

    public void Do(string jobName) {
        // 非同步執行任務
        ThreadPool.QueueUserWorkItem(_ => {
            BroadcastEvent(new CallbackEventArg(JobEventType.Started, jobName), OnStatusChanged);
            // 執行任務...
            BroadcastEvent(new CallbackEventArg(JobEventType.Completed, jobName), OnStatusChanged);
        });
    }

    // 廣播與非同步回調實作參考上文
}

總結

  1. 雙工廣播核心:靜態事件收集各會話回調委派 + 非同步 BeginInvoke 群發
  2. 會話生命週期控制:IsInitiating/IsTerminating 精準掌控會話啟動/終結
  3. 併發模式選擇:One-Way 回調 + Single Concurrency = 簡單高效;Multiple 需自管執行緒安全
  4. 非同步分層:服務端用委派/執行緒池,客戶端用 BackgroundWorker,職責分離
本文配套源碼下載:/Files/jillzhang/Jillzhang.Event.rar
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved