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

為 Windows 應用打造簡潔異步調用模式:自動回呼機制消除執行緒切換煩惱

     編輯:關於VC++

智慧型客戶端呼叫 Web Service 或長時間運算時,若阻塞 UI 執行緒會導致介面凍結。.NET Framework 雖提供 Begin/End 非同步模式(APM),但需手動處理 Control.Invoke 切回 UI 執行緒,程式碼冗長且易出錯。本文提出「自動回呼」模式,將執行緒切換與委派建立封裝於基底類別,讓 UI 程式碼僅需呼叫 BeginXxx 並實作 XxxCompleted 即可。

傳統 APM 痛點


// UI 事件處理
_proxy.BeginGetCustomerData("Joe", new AsyncCallback(CustomerDataCallback), null);

// 回呼在背景執行緒
void CustomerDataCallback(IAsyncResult ar) {
    var data = _proxy.EndGetCustomerData(ar);
    // 必須手動切回 UI 執行緒
    this.Invoke(new EventHandler(UpdateUI), null, null);
}
void UpdateUI(object s, EventArgs e) { dataGrid.DataSource = data; }

自動回呼模式:ServiceAgent 基底類別


public abstract class AutoCallbackServiceAgent {
    private readonly object _callbackTarget;
    protected AutoCallbackServiceAgent(object callbackTarget) { _callbackTarget = callbackTarget; }

    protected void InvokeAutoCallback(string methodName, object[] args, Type delegateType) {
        var callback = Delegate.CreateDelegate(delegateType, _callbackTarget, methodName);
        var ctrl = _callbackTarget as Control;
        if (ctrl != null && ctrl.InvokeRequired)
            ctrl.Invoke(callback, args);      // 切回 UI 執行緒
        else
            callback.DynamicInvoke(args);     // 已在正確執行緒或非 UI 物件
    }
}

具體服務代理實作


public class CustomerServiceAgent : AutoCallbackServiceAgent {
    private readonly CustomerWebService _proxy = new CustomerWebService();
    private delegate void GetCustomerDataCompletedCallback(DataSet data);

    public CustomerServiceAgent(object callbackTarget) : base(callbackTarget) {}

    public void BeginGetCustomerData(string id) {
        _proxy.BeginGetCustomerData(id, new AsyncCallback(GetCustomerDataCallback), null);
    }

    private void GetCustomerDataCallback(IAsyncResult ar) {
        var data = _proxy.EndGetCustomerData(ar);
        InvokeAutoCallback("GetCustomerDataCompleted", new object[]{data}, typeof(GetCustomerDataCompletedCallback));
    }
}

UI 端極致簡潔


private CustomerServiceAgent _agent = new CustomerServiceAgent(this);

private void btnLoad_Click(object sender, EventArgs e) {
    _agent.BeginGetCustomerData("Joe");   // 一行啟動
}

private void GetCustomerDataCompleted(DataSet data) {  // 自動在 UI 執行緒
    dataGrid.DataSource = data;
}

擴展性與進階議題

  • 統一委派簽章:若不想為每個回呼定義委派,可規範為 delegate void AutoCallback(object[] args),犧牲型別安全換取基底類別零委派定義。
  • 錯誤傳遞:在 InvokeAutoCallback 參數中攜帶 Exception 物件,UI 端統一處理失敗情境。
  • 快取與離線支援:ServiceAgent 可內建本地快取、重試邏輯、離線佇列,UI 完全無感。

此模式將「非同步啟動、執行緒切換、結果回呼」三大責任清晰分離,符合單一職責原則,大幅降低 UI 開發複雜度。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved