private void button4_Click(object sender, EventArgs e) { Debug.WriteLine(+ Thread.CurrentThread.ManagedThreadId); MyBeginXX(new AsyncCallback(t => { var result = MyEndXX(t); Debug.WriteLine(+ result.Trim().Substring(); Debug.WriteLine(+ Thread.CurrentThread.ManagedThreadId); })); Debug.WriteLine(+ Thread.CurrentThread.ManagedThreadId); }
效果图:
我们看到自己实现的效果基本上和系统提供的差不多。
【总结】
个人觉得APM异步模式就是启用另外一个线程执行耗时任务,然后通过回调函数执行后续操作。
APM还可以通过其他方式获取值,如:
while (!asyncResult.IsCompleted)//循环,直到异步执行完成 (轮询方式) { Thread.Sleep(100); } var stream2 = request.EndGetResponse(asyncResult).GetResponseStream();
或
asyncResult.AsyncWaitHandle.WaitOne();//阻止线程,直到异步完成 (阻塞等待) var stream2 = request.EndGetResponse(asyncResult).GetResponseStream();
补充:如果是普通方法,我们也可以通过委托异步:(BeginInvoke、EndInvoke)
public void MyAction() { var func = new Func<string, string>(t => { Thread.Sleep(2000); + t + DateTime.Now.ToString(); }); , t => { string str = func.EndInvoke(t); Debug.WriteLine(str); }, null); }
EAPEAP 基于事件的异步模式,Event-based Asynchronous Pattern
此模式在C#2的时候随之而来。
先来看个EAP的例子:
private void button3_Click(object sender, EventArgs e) { Debug.WriteLine(+ Thread.CurrentThread.ManagedThreadId); BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandler((s1, s2) => { Thread.Sleep(2000); Debug.WriteLine(+ Thread.CurrentThread.ManagedThreadId); });//注册事件来实现异步 worker.RunWorkerAsync(this); Debug.WriteLine(+ Thread.CurrentThread.ManagedThreadId); }
【效果图】(同样不会阻塞UI界面)
【特征】
例子很简单,但是和APM模式相比,是不是没有那么清晰透明。为什么可以这样实现?事件的注册是在干嘛?为什么执行RunWorkerAsync会触发注册的函数?
感觉自己又想多了...
我们试着反编译看看源码:
只想说,这么玩,有意思吗?
TAPTAP 基于任务的异步模式,Task-based Asynchronous Pattern
到目前为止,我们觉得上面的APM、EAP异步模式好用吗?好像没有发现什么问题。再仔细想想...如果我们有多个异步方法需要按先后顺序执行,并且需要(在主进程)得到所有返回值。
首先定义三个委托:
public Func<string, string> func1() { return new Func<string, string>(t => { Thread.Sleep(2000); + t; }); } public Func<string, string> func2() { return new Func<string, string>(t => { Thread.Sleep(2000); + t; }); } public Func<string, string> func3() { return new Func<string, string>(t => { Thread.Sleep(2000); + t; }); }
然后按照一定顺序执行: