C# 异步编程2 EAP 异步程序开发

在前面一篇博文记录了C# APM异步编程的知识,今天再来分享一下EAP(基于事件的异步编程模式)异步编程的知识。后面会继续奉上TPL任务并行库的知识,喜欢的朋友请持续关注哦。

EAP异步编程算是C#对APM的一种补充,让异步编程拥有了一系列状态事件。如果你看过本系列的前一篇文章《C# 异步编程1 APM 异步程序开发》,并假设你是微软C#语言开发组的一员,现在让你来设计基于事件的异步编程模式。那你是会利用之前的APM进行改造?还是进行再次创造呢?所以当你对相关dll进行反编译,会惊喜的发现EAP实际上是对APM增加了事件event后的封装。因此这篇博文的篇幅不会很长,我们只介绍EAP模式的基本信息和编程实现。对于事件 event 我后续增加博文阐述其功能及用法。

EAP 基于事件的异步编程模式

当我们使用EAP模式进行异步编程时,需要满足以下2个条件:

1、要进行异步的方法其方法名应该以XXXAsync结尾

2、要有一个名为XXXCompleted的事件监听异步方法的完成

3、可增加一个CancelAsync方法用于取消正在执行的异步方法(可选)

示例代码:

    /// <summary>
    /// EAP是对APM的封装
    /// </summary>
    public class Worker
    {
        public enum WorkerStatus
        {
            Cancel = 0,Running=1, Completed=2
        }
        public class WorkerEventArgs :EventArgs
        {
            public WorkerStatus Status { get; set; }
            public string Message { get; set; }
        }
        
        public Worker()
        {
        }
        public event EventHandler<WorkerEventArgs> OnWorkCompleted;
        IAsyncResult asyncResult = null;
        Thread thread = null;
        public void WorkAsync()
        {
            Worker _this = this;

            Action action = () =>
            {
                thread = Thread.CurrentThread;
                Thread.Sleep(10000);
                Console.WriteLine(string.Format("线程:{0},Work Over.", Thread.CurrentThread.ManagedThreadId));

            };
            asyncResult = action.BeginInvoke((result) =>
            {
                WorkerEventArgs e = null;
                try
                {
                    action.EndInvoke(asyncResult);
                }
                catch (ThreadAbortException ex)
                {
                    e = new WorkerEventArgs() { Status = WorkerStatus.Cancel, Message = "异步操作被取消" };
                }
                if (null != _this.OnWorkCompleted)
                {
                    _this.OnWorkCompleted.Invoke(this, e);
                }
            }, this);
        }

        public void CancelAsync()
        {
            if (null != thread)
                thread.Abort();
        }
    }

调用程序使用WinForm来进行,示例代码如下(仅为演示用):

        Worker worker;
        private void Btn_Start_Click(object sender, EventArgs e)
        {
            worker = new Worker();
            worker.OnWorkCompleted += WorkOver;
            worker.WorkAsync();
            Console.WriteLine(string.Format("线程:{0}", Thread.CurrentThread.ManagedThreadId));
        }
        private void Btn_Cancel_Click(object sender, EventArgs e)
        {
            worker.CancelAsync();
        }
        private void WorkOver(object sender, Worker.WorkerEventArgs e)
        {
            if (null != e)
            {
                if (Worker.WorkerStatus.Cancel == e.Status)
                {
                    MessageBox.Show(e.Message);
                }
            }
            else
            {
                Console.WriteLine(string.Format("线程:{0},委托回调完成.", Thread.CurrentThread.ManagedThreadId));
            }
        }

效果展示:

注意事项(重要):

1、APM异步编程时,因异步代码执行在单独的线程中,异步代码中出现的异常应该在调用EndXXX时捕获。

2、EAP异步编程时,因上述同样原因,代码中的异常信息会被传递到Completed事件的EventArgs参数中。

EAP(基于事件的异步编程模式)核心内容并不多,并且如网路、IO等耗时类 Ms 已添加了EAP相关异步功能,我们直接拿来用就好。尤其是后续TPL并行任务的加入,用户自定义EAP异步功能的机会更是了了,但EAP中相关的知识点如线程、委托、事件等仍然是重要的.......................

TPL任务并行库正在快马加鞭赶来中...............

posted @ 2017-09-10 09:41  DW039  阅读(1231)  评论(2编辑  收藏  举报