一、基于IAsyncResult构造一个异步API

  现在来构建一个IAsyncResult的类,并且实现异步调用。
// 带ref参数的自定义委托 
public delegate void RefAsyncCallback(ref string resultStr, IAsyncResult ar); 
  
public class CalculateAsyncResult : IAsyncResult 

    private int _calcNum1; 
    private int _calcNum2; 
    private RefAsyncCallback _userCallback; 
  
    public CalculateAsyncResult(int num1, int num2, RefAsyncCallback userCallback, object asyncState) 
    { 
        this._calcNum1 = num1; 
        this._calcNum2 = num2; 
        this._userCallback = userCallback; 
        this._asyncState = asyncState; 
        // 异步执行操作 
        ThreadPool.QueueUserWorkItem((obj) => { AsyncCalculate(obj); }, this); 
    } 
  
    #region IAsyncResult接口 
    private object _asyncState; 
    public object AsyncState { get { return _asyncState; } } 
  
    private ManualResetEvent _asyncWaitHandle; 
    public WaitHandle AsyncWaitHandle 
    { 
        get 
        { 
            if (this._asyncWaitHandle == null) 
            { 
                ManualResetEvent event2 = new ManualResetEvent(false); 
                Interlocked.CompareExchange<ManualResetEvent>(ref this._asyncWaitHandle, event2, null); 
            } 
            return _asyncWaitHandle; 
        } 
    } 
  
    private bool _completedSynchronously; 
    public bool CompletedSynchronously { get { return _completedSynchronously; } } 
  
    private bool _isCompleted; 
    public bool IsCompleted { get { return _isCompleted; } } 
    #endregion 
  
    /// <summary> 
    /// 
    /// 存储后结果值 
    /// </summary> 
    public int FinnalyResult { get; set; } 
    /// <summary> 
    /// End方法只应调用一次,超过一次报错 
    /// </summary> 
    public int EndCallCount = 0; 
    /// <summary> 
    /// ref参数 
    /// </summary> 
    public string ResultStr; 
  
    /// <summary> 
    /// 异步进行耗时计算 
    /// </summary> 
    /// <param name="obj">CalculateAsyncResult实例本身</param> 
    private static void AsyncCalculate(object obj) 
    { 
        CalculateAsyncResult asyncResult = obj as CalculateAsyncResult; 
        Thread.SpinWait(1000); 
        asyncResult.FinnalyResult = asyncResult._calcNum1 * asyncResult._calcNum2; 
        asyncResult.ResultStr = asyncResult.FinnalyResult.ToString(); 
  
        // 是否同步完成 
        asyncResult._completedSynchronously = false; 
        asyncResult._isCompleted = true; 
        ((ManualResetEvent)asyncResult.AsyncWaitHandle).Set(); 
        if (asyncResult._userCallback != null) 
            asyncResult._userCallback(ref asyncResult.ResultStr, asyncResult); 
    } 

  
public class CalculateLib 

    public IAsyncResult BeginCalculate(int num1, int num2, RefAsyncCallback userCallback, object asyncState) 
    { 
        CalculateAsyncResult result = new CalculateAsyncResult(num1, num2, userCallback, asyncState); 
        return result; 
    } 
  
    public int EndCalculate(ref string resultStr, IAsyncResult ar) 
    { 
        CalculateAsyncResult result = ar as CalculateAsyncResult; 
        if (Interlocked.CompareExchange(ref result.EndCallCount, 1, 0) == 1) 
        { 
            throw new Exception("End方法只能调用一次。"); 
        } 
        result.AsyncWaitHandle.WaitOne(); 
  
        resultStr = result.ResultStr; 
  
        return result.FinnalyResult; 
    } 
  
    public int Calculate(int num1, int num2, ref string resultStr) 
    { 
        resultStr = (num1 * num2).ToString(); 
        return num1 * num2; 
    } 
}