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

Windows 8 Store Apps 開發指南 (68):ControlChannel 後台任務實現持久 Socket 連線

     編輯:關於.NET

前言

Windows 8 引入 ControlChannelTrigger 機制,允許應用程式在進入暫停狀態後,仍能維持 TCP Socket 連線並在背景接收伺服器推送資料。這對於即時通訊、推播通知、遠端監控等長連線場景至關重要。本文深入解析 ControlChannel 的架構、關鍵類別與完整實作流程。

核心架構

ControlChannel 由三大角色組成:

  • ControlChannelTrigger:控制通道觸發器,管理連線槽位與心跳間隔。
  • KeepAlive Trigger 背景任務:定期向伺服器發送心跳封包,防止防火牆/NAT 斷開閒置連線。
  • Push Notification Trigger 背景任務:當 Socket 收到資料時喚醒應用處理訊息。

關鍵實作步驟

1. 共享上下文類別

使用靜態類別 AppContext 在前景應用與背景任務間共享 StreamSocket 與訊息佇列:

public class AppContext {
    public static ConcurrentQueue<string> MessageQueue = new ConcurrentQueue<string>();
    public static StreamSocket ClientSocket;
}

2. 建立 ControlChannel 與 Socket 連線

SocketControlChannel.CreateChannel() 方法完整示範:

public async Task<string> CreateChannel() {
    Dispose();
    try {
        // 申請硬體槽位,心跳間隔 15 分鐘(最小值)
        Channel = new ControlChannelTrigger(_channelId, _serverKeepAliveInterval, 
            ControlChannelTriggerResourceType.RequestHardwareSlot);
    } catch (Exception ex) {
        Dispose();
        return "控制通道建立失敗:" + ex.ToString();
    }

    // 註冊 KeepAlive 背景任務(需在 Package.appxmanifest 宣告)
    var keepAliveBuilder = new BackgroundTaskBuilder();
    keepAliveBuilder.Name = "myControlChannelKeepAlive";
    keepAliveBuilder.TaskEntryPoint = "BackgroundTaskLib.ControlChannelKeepAlive";
    keepAliveBuilder.SetTrigger(Channel.KeepAliveTrigger);
    keepAliveBuilder.Register();

    // 註冊 Push Notification 背景任務
    var pushBuilder = new BackgroundTaskBuilder();
    pushBuilder.Name = "myControlChannelPush";
    pushBuilder.TaskEntryPoint = "BackgroundTaskLib.ControlChannelPush";
    pushBuilder.SetTrigger(Channel.PushNotificationTrigger);
    pushBuilder.Register();

    // 建立 TCP 連線
    _socket = new StreamSocket();
    await _socket.ConnectAsync(new HostName("server.example.com"), "8080");
    AppContext.ClientSocket = _socket;

    _dataWriter = new DataWriter(_socket.OutputStream);
    _dataReader = new DataReader(_socket.InputStream);

    // 開始非同步接收迴圈
    ReceiveLoop();
    return "ControlChannel 建立成功";
}

3. 非同步接收迴圈

private async void ReceiveLoop() {
    try {
        while (true) {
            uint size = await _dataReader.LoadAsync(4); // 先讀長度前綴
            if (size < 4) break;
            int len = _dataReader.ReadInt32();
            uint loaded = await _dataReader.LoadAsync((uint)len);
            if (loaded < len) break;
            string msg = _dataReader.ReadString(len);
            AppContext.MessageQueue.Enqueue(msg);
        }
    } catch (Exception ex) {
        // 錯誤處理
    }
}

4. KeepAlive 背景任務實作

在獨立的 Background Task 專案中實作 IBackgroundTask:

public sealed class ControlChannelKeepAlive : IBackgroundTask {
    public void Run(IBackgroundTaskInstance taskInstance) {
        var deferral = taskInstance.GetDeferral();
        var channel = taskInstance.TriggerDetails as ControlChannelTrigger;
        if (channel != null && AppContext.ClientSocket != null) {
            try {
                // 發送心跳封包
                var writer = new DataWriter(AppContext.ClientSocket.OutputStream);
                writer.WriteInt32(0); // 空心跳
                await writer.StoreAsync();
            } catch { /* 忽略 */ }
        }
        deferral.Complete();
    }
}

5. Push Notification 背景任務處理接收資料

public sealed class ControlChannelPush : IBackgroundTask {
    public void Run(IBackgroundTaskInstance taskInstance) {
        var deferral = taskInstance.GetDeferral();
        var details = taskInstance.TriggerDetails as ControlChannelTriggerEventDetails;
        if (details != null && AppContext.ClientSocket != null) {
            // 讀取資料並加入佇列,前景應用恢復時可取出處理
            // 此處略...
        }
        deferral.Complete();
    }
}

重要注意事項

  1. Manifest 宣告:必須在 Package.appxmanifest 的「宣告」頁籤加入「背景工作」,類型選「控制通道」,並正確填寫 EntryPoint。
  2. 同機測試限制:Client 與 Socket Server 不可部署在同一台機器,否則會拋出 0x8007273D 例外。
  3. 資源類型選擇:RequestHardwareSlot 較可靠但槽位有限;RequestSoftwareSlot 無限制但可能被系統回收。
  4. WebSocket 替代方案:若使用 WebSocket 協定,系統內建心跳邏輯,KeepAlive TaskEntryPoint 可直接指定 Windows.Networking.Sockets.WebSocketKeepAlive,無需自行實作。

總結

ControlChannel 為 Windows 8 Store Apps 提供了真正的後台長連線能力。雖然設定流程較繁瑣(Manifest、背景任務專案、觸發器註冊),但一旦建立穩定,即能實現低延遲、低功耗的即時資料傳輸。建議封裝成可重用的 SocketControlChannel 元件,並妥善處理例外、重連與生命週期管理。

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