Windows 8 Store Apps學習(68) 背景工作:控制通道(ControlChannel)

來源:互聯網
上載者:User

介紹

重新想象 Windows 8 Store Apps 之 背景工作

控制通道(ControlChannel)

樣本

1、用戶端與服務端做 ControlChannel 通訊的關鍵代碼

ControlChannelHelper/AppContext.cs

/* * 本例通過全域靜態變數來實現 app 與 task 的資訊共用,以便背景工作可以擷取到 app 中的相關資訊 *  * 註: * 也可以通過 Windows.ApplicationModel.Core.CoreApplication.Properties 儲存資料,以實現 app 與 task 的資訊共用 */    using System.Collections.Concurrent;using Windows.Networking.Sockets;    namespace ControlChannelHelper{    public class AppContext    {        /// <summary>        /// 從 ControlChannel 接收到的資料        /// </summary>        public static ConcurrentQueue<string> MessageQueue = new ConcurrentQueue<string>();            /// <summary>        /// 用戶端 socket        /// </summary>        public static StreamSocket ClientSocket;    }}

ControlChannelHelper/SocketControlChannel.cs

/* * 實現一個 socket tcp 通訊的 ControlChannel,client 將在此 ControlChannel 中即時接收資料 *  * 註: * win8 client 和 socket server 不能部署在同一台機器上,否則會拋出異常:{參考的物件類型不支援嘗試的操作。 (異常來自 HRESULT:0x8007273D)} */    using System;using System.Threading.Tasks;using Windows.ApplicationModel.Background;using Windows.Foundation;using Windows.Networking;using Windows.Networking.Sockets;using Windows.Storage.Streams;    namespace ControlChannelHelper{    public class SocketControlChannel : IDisposable    {        // ControlChannel        public ControlChannelTrigger Channel { get; set; }            // 用戶端 socket        private StreamSocket _socket;        // 用於發送資料        private DataWriter _dataWriter;        // 用於接收資料        private DataReader _dataReader;            // 向服務端發送心跳的間隔時間,單位為分鐘,最小 15 分鐘        private uint _serverKeepAliveInterval = 15;        // ControlChannel 的標識        private string _channelId = "myControlChannel";            public SocketControlChannel()        {            }            public async Task<string> CreateChannel()        {            Dispose();                try            {                // 執行個體化一個 ControlChannel                Channel = new ControlChannelTrigger(_channelId, _serverKeepAliveInterval, ControlChannelTriggerResourceType.RequestHardwareSlot);            }            catch (Exception ex)            {                Dispose();                return "控制通道建立失敗:" + ex.ToString();            }                // 註冊用於向服務端 socket 發送心跳的背景工作,需要在 manifest 中做相關配置            var keepAliveBuilder = new BackgroundTaskBuilder();            keepAliveBuilder.Name = "myControlChannelKeepAlive";            // 註:如果走的是 WebSocket 通訊協定,則系統已經為其內建了發送心跳的邏輯,此處直接指定為 Windows.Networking.Sockets.WebSocketKeepAlive 即可            keepAliveBuilder.TaskEntryPoint = "BackgroundTaskLib.ControlChannelKeepAlive";            keepAliveBuilder.SetTrigger(Channel.KeepAliveTrigger); // 到了發送心跳的間隔時間時則觸發,本例是 15 分鐘            keepAliveBuilder.Register();                // 註冊用於向使用者顯示通知的背景工作,需要在 manifest 中做相關配置// 查看本欄目更多精彩內容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/net/            var pushNotifyBuilder = new BackgroundTaskBuilder();            pushNotifyBuilder.Name = "myControlChannelPushNotification";            pushNotifyBuilder.TaskEntryPoint = "BackgroundTaskLib.ControlChannelPushNotification";            pushNotifyBuilder.SetTrigger(Channel.PushNotificationTrigger); // 在 ControlChannel 中收到了推送過來的資料時則觸發            pushNotifyBuilder.Register();                try            {                _socket = new StreamSocket();                AppContext.ClientSocket = _socket;                    // 在 ControlChannel 中通過指定的 StreamSocket 通訊                Channel.UsingTransport(_socket);                    // client socket 串連 server socket                await _socket.ConnectAsync(new HostName("192.168.6.204"), "3366");                    // 開始等待 ControlChannel 中推送過來的資料,如果 win8 client 和 socket server 部署在同一台機器上,則此處會拋出異常                ControlChannelTriggerStatus status = Channel.WaitForPushEnabled();                    if (status != ControlChannelTriggerStatus.HardwareSlotAllocated && status != ControlChannelTriggerStatus.SoftwareSlotAllocated)                    return "控制通道建立失敗:" + status.ToString();                    // 發送資料到服務端                _dataWriter = new DataWriter(_socket.OutputStream);                string message = "hello " + DateTime.Now.ToString("hh:mm:ss") + "^";                _dataWriter.WriteString(message);                await _dataWriter.StoreAsync();                    // 接收資料                ReceiveData();            }            catch (Exception ex)            {                Dispose();                return "控制通道建立失敗:" + ex.ToString();            }                return "ok";        }            // 開始接收此次資料        private void ReceiveData()        {            uint maxBufferLength = 256;                try            {                var buffer = new Windows.Storage.Streams.Buffer(maxBufferLength);                var asyncOperation = _socket.InputStream.ReadAsync(buffer, maxBufferLength, InputStreamOptions.Partial);                asyncOperation.Completed = (IAsyncOperationWithProgress<IBuffer, uint> asyncInfo, AsyncStatus asyncStatus) =>                {                    switch (asyncStatus)                    {                        case AsyncStatus.Completed:                        case AsyncStatus.Error:                            try                            {                                IBuffer bufferRead = asyncInfo.GetResults();                                uint bytesRead = bufferRead.Length;                                _dataReader = DataReader.FromBuffer(bufferRead);                                    // 此次資料接收完畢                                ReceiveCompleted(bytesRead);                            }                            catch (Exception ex)                            {                                AppContext.MessageQueue.Enqueue(ex.ToString());                            }                            break;                        case AsyncStatus.Canceled:                            AppContext.MessageQueue.Enqueue("接收資料時被取消了");                            break;                    }                };            }            catch (Exception ex)            {                AppContext.MessageQueue.Enqueue(ex.ToString());            }        }            public void ReceiveCompleted(uint bytesRead)        {            // 擷取此次接收到的資料            uint bufferLength = _dataReader.UnconsumedBufferLength;            string message = _dataReader.ReadString(bufferLength);                // 將接收到的資料放到記憶體中,由 PushNotificationTrigger 觸發的後台任進行處理(當然也可以在此處處理)            AppContext.MessageQueue.Enqueue(message);                // 開始接收下一次資料            ReceiveData();        }            // 釋放資源        public void Dispose()        {            lock (this)            {                if (_dataWriter != null)                {                    try                    {                        _dataWriter.DetachStream();                        _dataWriter = null;                    }                    catch (Exception ex)                    {                        }                }                    if (_dataReader != null)                {                    try                    {                        _dataReader.DetachStream();                        _dataReader = null;                    }                    catch (Exception exp)                    {                        }                }                    if (_socket != null)                {                    _socket.Dispose();                    _socket = null;                }                    if (Channel != null)                {                    Channel.Dispose();                    Channel = null;                }            }        }    }}

2、服務端

BackgroundTaskLib/ControlChannelKeepAlive.cs

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.