同步编程,服务器在响A服务的数据库读取,网页请求或者文件请求(这里咱们统称为IO操做),若是延迟很大,此时若是来了B服务的IO请求,可能没法及时响应(阻塞),此时异步编程模式(非阻塞)应运而生。html
异步编程模式是为了不性能瓶颈并加强你的应用程序的整体响应能力。git
APM(Asynchronous Programming Model) 是 net 1.0时期就提出的一种异步模式,而且基于IAsyncResult接口实现BeginXXX和EndXXX相似的方法.github
class Program { static void Main(string[] args) { Console.WriteLine("===== 异步调用 AsyncInvokeTest ====="); WebResponseHandler handler = new WebResponseHandler(WebContentLength.GetResult); //IAsyncResult: 异步操做接口(interface) //BeginInvoke: 委托(delegate)的一个异步方法的开始 IAsyncResult result = handler.BeginInvoke( null, null); Console.WriteLine("继续作别的事情。"); //异步操做返回 Console.WriteLine(handler.EndInvoke(result)); Console.ReadKey(); } } public delegate string WebResponseHandler(); public class WebContentLength { public static string GetResult() { var client = new WebClient(); var content = client.DownloadString(new Uri("http://cnblogs.com")); return "网页字数统计:"+content.Length; } }
备注:APM又是创建在委托之上的。Net Core中的委托 不支持异步调用,也就是 BeginInvoke 和 EndInvoke 方法,即现代异步编程模型中,官方不推荐此模型。此例子使用 .Net FrameWork4.7框架。数据库
当异步请求响应完成以后,会自动去调用回调方法,将网页字数统计结果打印。编程
class Program { static void Main(string[] args) { Console.WriteLine("===== 异步回调 AsyncInvokeTest ====="); WebResponseHandler handler = new WebResponseHandler(WebContentLength.GetResult); //异步操做接口(注意BeginInvoke方法的不一样!) IAsyncResult result = handler.BeginInvoke( new AsyncCallback(CalllBack), "AsycState:OK"); Console.WriteLine("继续作别的事情。"); Console.ReadKey(); } static void CalllBack(IAsyncResult result) { WebResponseHandler handler = (WebResponseHandler)((AsyncResult)result).AsyncDelegate; Console.WriteLine(handler.EndInvoke(result)); Console.WriteLine(result.AsyncState); } } public delegate string WebResponseHandler(); public class WebContentLength { public static string GetResult() { var client = new WebClient(); var content = client.DownloadString(new Uri("http://cnblogs.com")); return "网页字数统计:" + content.Length; } }
备注:能够看出此种回调方式与人的思惟逻辑相违背,当在回调函数中存在二级三级回调时,代码可读性变差,编程会变得比日常要困难一些。服务器
EAP(Event-based Asynchronous Pattern)基于事件的异步模式是 .net 2.0提出的,EAP异步编程算是C#对APM的一种补充,让异步编程拥有了一系列状态事件。实现了基于事件的异步模式的类将具备一个或者多个以Async为后缀的方法和对应的Completed事件,而且这些类都支持异步方法的取消、进度报告和报告结果。然而.net中并非全部的类都支持EAP。网络
当咱们使用EAP模式进行异步编程时,须要知足如下2个条件:框架
备注:当调用基于事件的EAP模式的类的XXXAsync方法时,就开始了一个异步操做,而且基于事件的EAP模式是基于APM模式之上的。EAP 是在 .NET Framework 2.0 版中引入的,在 winform,silverlight或者wpf变成中常常用到。异步
class Program { static void Main(string[] args) { WebClient wc = new WebClient(); wc.DownloadStringCompleted += Wc_DownloadStringCompleted; wc.DownloadStringAsync(new Uri("http://www.baidu.com")); Console.WriteLine("执行其余任务。"); Console.ReadKey(); } private static void Wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { Console.WriteLine("网页字数统计:" + e.Result.Length); } }
总结:此示例代码的编程模式有没有种似曾相识的感受。没错,winform,wpf等的点击事件,网络库的接收方法中采用事件驱动型的异步编程模式。async
示例代码以下:
Work类,以下代码使用了了事件驱动型异步编程模式,而且对APM模式进行了封装。
/// <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(1000); Console.WriteLine(string.Format("线程:{0},Work Over.", Thread.CurrentThread.ManagedThreadId)); }; //result是IAsyncResult对象,此处无用 //当action委托完成调用以后,会调用以下回调方法。 asyncResult = action.BeginInvoke((result) => { WorkerEventArgs e = null; try { action.EndInvoke(result); } 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调用例子
异步嗲用WorkAsync,完成以后,事件异步调用WorkOver方法,并传入EventArgs参数。
public partial class Form1 : Form { public Form1() { InitializeComponent(); } Worker worker; private void btnStart_Click(object sender, EventArgs e) { worker = new Worker(); worker.OnWorkCompleted += WorkOver; worker.WorkAsync(); Console.WriteLine(string.Format("线程:{0}", Thread.CurrentThread.ManagedThreadId)); } private void btnCancel_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)); } } }
注意事项(重要):
预告: 深刻理解C#中的异步(二)——TAP模式(基于Async,Await,Task的异步)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接和本声明。 本文连接:https://www.cnblogs.com/JerryMouseLi/p/14100496.html