模式1、APM异步编程模型 Net1.0 [Asynchronous Programming Mode]
2016-11-20 17:45
344 查看
BeginXXX方法和EndXXX方法是这个编程模型的标识之一,看到这个是不是好像在哪见过?是的没有错,那就是委托的BeginXXX方法和EndXXX方法。(当然还有跨线程调用的BeginInvoke 这个可以另开一片文章来讨论了)
看完代码是不是想问IAsyncResult 是啥?(主要作用就是提供阻塞功能和保存原委托的执行状态) 定义如下:
总的来说把AMP这个过程就是把一个Delegate异步化的一个过程 ,了解了以上微软对Delegate的APM异步改造之路后 我们自己尝试对一个同步方法进行改造
首先我们改造的同步方法如下:
参考:http://www.cnblogs.com/heyuquan/archive/2013/03/22/Asynchronous-Programming-Model.html
delegate int TestDelegate(int numA, int numB, out long ticks); public static void Test3() { long ticks = 0; TestDelegate testD = AddNum; IAsyncResult result1 = testD.BeginInvoke(1, 100, out ticks, null, null); //可能回引起主线程阻塞 testD.EndInvoke(out ticks, result1); //回调中调用EndXXX不会引起主线程阻塞 IAsyncResult result2 = testD.BeginInvoke(1, 100, out ticks, (d) => { testD.EndInvoke(out ticks, d); }, null); testD.EndInvoke(out ticks, result2); }
看完代码是不是想问IAsyncResult 是啥?(主要作用就是提供阻塞功能和保存原委托的执行状态) 定义如下:
// 表示异步操作的状态。 [ComVisible(true)] public interface IAsyncResult { // 获取用户定义的对象,它限定或包含关于异步操作的信息。 object AsyncState { get; } // 获取用于等待异步操作完成的System.Threading.WaitHandle,待异步操作完成时获得信号。 WaitHandle AsyncWaitHandle { get; } // 获取一个值,该值指示异步操作是否同步完成。 bool CompletedSynchronously { get; } // 获取一个值,该值指示异步操作是否已完成。 bool IsCompleted { get; } }
BeingXXX是什么套路?
public IAsyncResult BeginXXX(object[] parameters, AsyncCallback callback, object asyncState) //parameters 原委托的所有参数 //callback 回调函数,当原委托执行完之后开始调用 //asyncState 用户自定义参数
EndXXX是什么套路?
EndXXX通常情况下只有一个参数那就是IAsyncResult,但是如果原委托中含有 out ref 修饰的参数 那么EndXXX也得带这个参数(要不怎么赋值)总的来说把AMP这个过程就是把一个Delegate异步化的一个过程 ,了解了以上微软对Delegate的APM异步改造之路后 我们自己尝试对一个同步方法进行改造
首先我们改造的同步方法如下:
/// <summary> /// 从numA累加倒numB /// </summary> /// <param name="numA">开始数</param> /// <param name="numB">结束数</param> /// <param name="ticks">耗时</param> /// <returns>计算结果</returns> public static int AddNum(int numA, int numB, out long ticks) { Stopwatch st = new Stopwatch(); st.Start(); int result = 0; for (int i = numA; i < numB; i++) { Console.WriteLine(i); result += i; } st.Stop(); ticks = st.ElapsedTicks; return result; }
改造第一步:(定义一个实现了IAsyncReuslt的类来实现 同步方法的状态的记录以及阻塞的实现)
/// <summary> /// 一个类似仿照AsyncCallback的回调委托 /// </summary> /// <param name="time"></param> /// <param name="ar"></param> public delegate void RefAsyncCallback(out long time, IAsyncResult ar); public class CalculateAsyncResult : IAsyncResult { int numA, numB; RefAsyncCallback userCallback; public CalculateAsyncResult(int numA, int numB, RefAsyncCallback userCallback, object asyncState) { this.numA = numA; this.numB = numB; this.userCallback = userCallback; this.asyncState = asyncState; ThreadPool.QueueUserWorkItem((obj) => { AsyncCalculate(obj); }, this); } #region 接口实现部分 object asyncState; ManualResetEvent asyncWaiHandle; bool completedSynchronously; bool isCompleted; public object AsyncState { get { return asyncState; } } public WaitHandle AsyncWaitHandle { get { if (asyncWaiHandle == null) { //用于EndXXX中的阻塞 ManualResetEvent event2 = new ManualResetEvent(false); //如果asyncWaiHandle为空就给它赋值event2 Interlocked.CompareExchange(ref asyncWaiHandle, event2, null); } return asyncWaiHandle; } } public bool CompletedSynchronously { get { return completedSynchronously; } } public bool IsCompleted { get { return isCompleted; } } #endregion //最后结果 public int FinnalyResult { get; set; } //endxx调用次数 public int EndCallCount = 0; //out参数 public long ticks; private static void AsyncCalculate(object obj) { CalculateAsyncResult asyncReuslt = obj as CalculateAsyncResult; Stopwatch st = new Stopwatch(); st.Start(); int result = 0; for (int i = asyncReuslt.numA; i < asyncReuslt.numB; i++) { Console.WriteLine(i); result += i; } st.Stop(); asyncReuslt.ticks = st.ElapsedTicks; asyncReuslt.completedSynchronously = false; asyncReuslt.isCompleted = true; (asyncReuslt.asyncWaiHandle as ManualResetEvent).Set(); //原来二元式还能这么用。。vs2015的小灯泡说的 asyncReuslt.userCallback不为空就调用 666 asyncReuslt.userCallback?.Invoke(out asyncReuslt.ticks, asyncReuslt); } }
改造第二步:(定义BeginXXX 和EndXXX)
public class CalculateLib { /// <summary> /// 传说的BebinXXX /// </summary> /// <param name="numA">开始数</param> /// <param name="numB">结束数</param> /// <param name="userCallback">回调委托</param> /// <param name="asyncState">自定义对象(此参数可以在IAsyncResult对象中获取到)</param> /// <returns>返回一个可以获取原委托执行状态的对象</returns> public IAsyncResult BeginCalculate(int numA, int numB, RefAsyncCallback userCallback, object asyncState) { return new CalculateAsyncResult(numA, numB, userCallback, asyncState); } /// <summary> /// 传说中的EndXXX /// </summary> /// <param name="ticks">耗时</param> /// <param name="ar">要End的IAsyncResult对象</param> /// <returns>计算结果</returns> public int EndCalculate(out long ticks, IAsyncResult ar) { CalculateAsyncResult result = ar as CalculateAsyncResult; if (Interlocked.CompareExchange(ref result.EndCallCount, 1, 0) == 1) { throw new Exception("此方法只能调用一次"); } //等着的开门放狗的信号 result.AsyncWaitHandle.WaitOne(); ticks = result.ticks; return result.FinnalyResult; } }
改造完成开始i调用:
public class TestClass { #region 传统思维调用,可能导致主线程阻塞 从而界面假死 public static void Test1() { CalculateLib cal = new CalculateLib(); IAsyncResult calculateResult = cal.BeginCalculate(1, 100, null, null); long times = 0; int result = cal.EndCalculate(out times, calculateResult); } #endregion #region 回调中调用EndXXX思维调用,不会导致主线程阻塞 public static void Test2() { CalculateLib cal = new CalculateLib(); IAsyncResult CalculateResult = cal.BeginCalculate(1, 100, null, cal); } public static void AfterCallback(out long tiems, IAsyncResult ar) { CalculateLib cal = ar.AsyncState as CalculateLib; cal.EndCalculate(out tiems, ar); } #endregion }
参考:http://www.cnblogs.com/heyuquan/archive/2013/03/22/Asynchronous-Programming-Model.html
相关文章推荐
- .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)
- Asynchronous Programming Model (APM)异步编程模型
- 异步编程模型(APM,Asynchronous Programming Model)
- CLR via C# 读书笔记 3-6 比较APM和EAP(异步编程模型和基于事件的编程模式)
- 模式3、基于任务的异步编程模型(TAP .Net4.x)[Task-based Asynchronous Pattern]
- 异步编程模型(APM)模式
- .NET中的异步编程 - EAP/APM
- C# 线程知识--异步编程模型(APM)
- [你必须知道的异步编程]——异步编程模型(APM)
- Asynchronous Programming Model in .NET 2.0
- 理解实体模型的刷新模式RefreshMode.ClientWins
- 异步编程:IAsyncResult异步编程模型 (APM)
- 异步编程(2)——.NET的异步编程模型
- .Net中的异步编程模式 (APM) (一)
- APM (异步编程模型)
- 异步编程模型APM(2)
- asp.net ajax1.0基础回顾(二):经典模式
- 异步编程(2)——.NET的异步编程模型
- Introduction to Asynchronous Programming in .NET 2.0
- .Net中的异步编程模式 ,APM