C#中的非同步呼叫及非同步設計模式(三)——事件架構非同步模式

來源:互聯網
上載者:User

 

四、事件架構非同步模式(設計層面)

基於事件的C#非同步編程模式是比IAsyncResult模式更進階的一種非同步編程模式,也被用在更多的場合。該非同步模式具有以下優點:

·                  “在後台”執行耗時任務(例如下載和資料庫操作),但不會中斷您的應用程式。

·                  同時執行多個操作,每個操作完成時都會接到通知(在通知中可以區分是完成了哪個操作)。

·                  等待資源變得可用,但不會停止(“掛起”)您的應用程式。

·                  使用熟悉的事件和委託模型與掛起的非同步作業通訊。

對於相對簡單的應用程式可以直接用 .Net 2.0 新增的 BackgroundWorker 組件來很方便的實現,對於更複雜的非同步應用程式則需要自己實現一個符合基於事件的C#非同步編程模式的類。在實現事件架構非同步模式的設計前,需要瞭解事件架構非同步模式的實現原理是什麼。事件架構非同步模式需要以下三個類型的協助。

AsyncOperation:提供了對非同步作業的生存期進行跟蹤的功能,包括操作進度通知和操作完成通知,並確保在正確的線程或上下文中調用用戶端的事件處理常式。

public void Post(SendOrPostCallback d,Object arg);

public void PostOperationCompleted(SendOrPostCallback d,Object arg);

通過在非同步輔助代碼中調用Post方法把進度和中間結果報告給使用者,如果是取消非同步任務或提示非同步任務已完成,則通過調用PostOperationCompleted方法結束非同步作業的跟蹤生命期。在PostOperationCompleted方法調用後,AsyncOperation對象變得不再可用,再次訪問將引發異常。在此有個問題:在該非同步模式中,通過AsyncOperation的Post函數來通知進度的時候,是如何使SendOrPostCallback委託在UI線程上執行的?針對該問題下文有具體分析。

 

AsyncOperationManager:為AsyncOperation對象的建立提供了便捷方式,通過CreateOperation方法可以建立多個AsyncOperation執行個體,實現對多個非同步作業進行跟蹤。

 

WindowsFormsSynchronizationContext:該類繼承自SynchronizationContext類型,提供 Windows 表單應用程式模型的同步上下文。該類型是基於事件非同步模式通訊的核心。之所以說該類型是基於事件非同步模式的通訊核心,是因為該類型解決了“保證SendOrPostCallback委託在UI線程上執行”的問題。它是如何解決的?請看AsyncOperation類型的Post方法的實現:

        /// <summary>           /// AsyncOperation類型的Post方法的實現           /// </summary>        public void Post(SendOrPostCallback d, object arg)        {            this.VerifyNotCompleted();            this.VerifyDelegateNotNull(d);            this.syncContext.Post(d, arg);        }

 

在AsyncOperation類型的Post方法中,直接調用了SynchronizationContext類型的Post方法,再看該Post方法的實現:

        /// <summary>           /// WindowsFormsSynchronizationContext類型的Post方法的實現           /// </summary>        public override void Post(SendOrPostCallback d, object state)        {            if (this.controlToSendTo != null)            {                this.controlToSendTo.BeginInvoke(d, new object[] { state }); //此處保證了SendOrPostCallBack委託在UI線程上執行            }        }

 

有以上三個類型(AsyncOpertion,AsyncOperationManager和SynchronizationContext)作為基礎,實現事件架構非同步模式的進度通知和完成通知就輕鬆多了。下面用一個基於事件的非同步模型的例子來結束本文章。

using System;using System.Collections.Generic;using System.Text;using System.ComponentModel;using System.Collections.Specialized;using System.Threading;namespace test{    /// <summary>    /// 任務1的進度通知代理    /// </summary>    /// <param name="sender"></param>    /// <param name="e"></param>    public delegate void Work1ProgressChangedEventHandler(object sender, Work1ProgressChangedEventArgs e);    /// <summary>    /// 任務1的進度通知參數    /// </summary>    /// <param name="sender"></param>    /// <param name="e"></param>    public delegate void Work1CompletedEventHandler(object sender, Work1CompletedEventArgs e);    public class BasedEventAsyncWorker    {        private delegate void WorkerEventHandler(int maxNumber, AsyncOperation asyncOp);        private HybridDictionary userStateToLifetime = new HybridDictionary();        public BasedEventAsyncWorker()        { }        #region DoWork1的基於事件的非同步呼叫        public void DoWork1Async(object userState, int maxNumber)        {            AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState);            //userStateToLifetime有可能會同時被多線程訪問,在此需要lock進行同步處理            lock (userStateToLifetime.SyncRoot)            {                if (userStateToLifetime.Contains(userState))                {                    throw new ArgumentException(                        "userState parameter must be unique",                        "userState");                }                userStateToLifetime[userState] = asyncOp;            }            //非同步開始任務1            WorkerEventHandler workerDelegate = new WorkerEventHandler(DoWork1);            workerDelegate.BeginInvoke(maxNumber, asyncOp, null, null);        }        private void DoWork1(int maxNumber, AsyncOperation asyncOp)        {            Exception e = null;            //判斷該userState的任務仍在處理中            if (!TaskCanceled(asyncOp.UserSuppliedState))            {                try                {                    int n = 0;                    int percentage = 0;                    while (n < maxNumber && !TaskCanceled(asyncOp.UserSuppliedState))                    {                        Thread.Sleep(100); //類比耗時操作                        percentage = (int)((float)n / (float)maxNumber * 100);                        Work1ProgressChangedEventArgs progressChanageArgs =                            new Work1ProgressChangedEventArgs(maxNumber, percentage, asyncOp.UserSuppliedState);                        //任務1的進度通知                        asyncOp.Post(new SendOrPostCallback(Work1ReportProgressCB), progressChanageArgs);                         n++;                    }                }                catch (Exception ex)                {                    e = ex;                }            }            this.Work1Complete(e, TaskCanceled(asyncOp.UserSuppliedState), asyncOp);        }        private void Work1Complete(Exception exception, bool canceled, AsyncOperation asyncOp)        {            if (!canceled)            {                lock (userStateToLifetime.SyncRoot)                {                    userStateToLifetime.Remove(asyncOp.UserSuppliedState);                }            }            Work1CompletedEventArgs e = new Work1CompletedEventArgs(exception, canceled, asyncOp.UserSuppliedState);            //通知指定的任務已經完成            asyncOp.PostOperationCompleted(new SendOrPostCallback(Work1CompleteCB), e);            //調用 PostOperationCompleted 方法來結束非同步作業的生存期。            //為某個特定任務調用此方法後,再調用其相應的 AsyncOperation 對象會引發異常。        }        private void Work1ReportProgressCB(object state)        {            Work1ProgressChangedEventArgs e = state as Work1ProgressChangedEventArgs;            OnWork1ProgressChanged(e);        }        private void Work1CompleteCB(object state)        {            Work1CompletedEventArgs e = state as Work1CompletedEventArgs;            OnWork1Completed(e);        }        #region Work1的進度通知和任務完成的事件        public event Work1ProgressChangedEventHandler Work1ProgressChanged;        protected virtual void OnWork1ProgressChanged(Work1ProgressChangedEventArgs e)        {            Work1ProgressChangedEventHandler temp = this.Work1ProgressChanged;            if (temp != null)            {                temp(this, e);            }        }        public event Work1CompletedEventHandler Work1Completed;        protected virtual void OnWork1Completed(Work1CompletedEventArgs e)        {            Work1CompletedEventHandler temp = this.Work1Completed;            if (temp != null)            {                temp(this, e);            }        }         #endregion         #endregion        /// <summary>        /// 取消指定userState的任務執行        /// </summary>        /// <param name="userState"></param>        public void CancelAsync(object userState)        {            AsyncOperation asyncOp = userStateToLifetime[userState] as AsyncOperation;            if (asyncOp != null)            {                lock (userStateToLifetime.SyncRoot)                {                    userStateToLifetime.Remove(userState);                }            }        }        /// <summary>        /// 判斷指定userState的任務是否已經被結束。傳回值:true 已經結束; false 還沒有結束        /// </summary>        /// <param name="userState"></param>        /// <returns></returns>        private bool TaskCanceled(object userState)        {            return (userStateToLifetime[userState] == null);        }    }    public class Work1ProgressChangedEventArgs :ProgressChangedEventArgs    {        private int totalWork = 1;        public Work1ProgressChangedEventArgs(int totalWork, int progressPercentage, object userState)            : base(progressPercentage, userState)        {            this.totalWork = totalWork;        }        /// <summary>        /// Work1的總工作量        /// </summary>        public int TotalWork        {            get            {                return totalWork;            }        }    }    public class Work1CompletedEventArgs : AsyncCompletedEventArgs    {        public Work1CompletedEventArgs(Exception e, bool canceled, object state)            : base(e, canceled, state)        {        }    }}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.