博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

.NET的异步调用和IAsyncResult接口

Posted on 2009-12-28 21:36  生鱼片  阅读(2854)  评论(2编辑  收藏  举报

1.关于委托的BeginInvokeEndInvoke方法

.NET Framework 允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义 BeginInvoke EndInvoke 方法。

例如:

namespace carydemo2

{

    public class CaryAsync

    {       

        public string LongtimeOperation(int data, out int threadId)

        {

            Console.WriteLine("Long time operation begin");

            data = data + 123;

            Thread.Sleep(500);

            threadId = Thread.CurrentThread.ManagedThreadId;

            return String.Format("Data:{0}.", data.ToString());

        }

    }

   

    public delegate string CaryAsyncCaller(int data, out int threadId);

    public class CaryTest

    {

        private static int threadId;

        public static void Main()

        {           

            CaryAsync ca = new CaryAsync();

            CaryAsyncCaller caller = new CaryAsyncCaller(ca.LongtimeOperation);

            IAsyncResult result = caller.BeginInvoke(3000, out threadId, null, null);

            Thread.Sleep(0);

            Console.WriteLine("Main thread :{0}", Thread.CurrentThread.ManagedThreadId);

            result.AsyncWaitHandle.WaitOne();

            while (result.IsCompleted == false)

            {

                Thread.Sleep(10);

            }

            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("The caller thread: {0}, Data :\"{1}\".", threadId, returnValue);

        }     

    }

}

调用你可以使用 BeginInvoke 返回的 IAsyncResult AsyncWaitHandle 属性来获取 WaitHandle。异步调用完成时会发出 WaitHandle 信号,而您可以通过调用 WaitOne 方法等待它。这样你就可以在异步调用完成之前或之后,在通过调用 EndInvoke 检索结果之前,还可以执行其他处理。 

可以使用由 BeginInvoke 返回的 IAsyncResult IsCompleted 属性来发现异步调用何时完成。 

还可以在调用完成时执行回调方法,代码如下:

    public class CaryTest

    {

        private static int threadId;

        public static void Main()

        {           

            CaryAsync ca = new CaryAsync();

            CaryAsyncCaller caller = new CaryAsyncCaller(ca.LongtimeOperation);

            IAsyncResult result = caller.BeginInvoke(3000, out threadId, new AsyncCallback(CaryCallBack), caller);

            Console.ReadLine();

 

        }

 

        static void CaryCallBack(IAsyncResult ar)

        {

            CaryAsyncCaller caller = (CaryAsyncCaller)ar.AsyncState;

            string returnValue = caller.EndInvoke(out threadId, ar);

            Console.WriteLine("The caller thread:{0},return value\"{1}\"", threadId, returnValue);

        }

    }

 

2.IAsyncResult接口:它表示异步操作的状态.该接口定义了4个公用属性,如下:

   AsyncState  获取用户定义的对象,它限定或包含关于异步操作的信息。

   AsyncWaitHandle  获取用于等待异步操作完成的 WaitHandle

   CompletedSynchronously  获取异步操作是否同步完成的指示。

   IsCompleted  获取异步操作是否已完成的指示。 

 

IAsyncResult 接口由包含可异步操作的方法的类实现。它是启动异步操作的方法的返回类型,如 FileStream.BeginRead,也是结束异步操作的方法的第三个参数的类型,如 FileStream.EndRead。当异步操作完成时,IAsyncResult 对象也将传递给由 AsyncCallback 委托调用的方法。 

支持 IAsyncResult 接口的对象存储异步操作的状态信息,并提供同步对象以允许线程在操作完成时终止。 

3. AsyncCallback 委托      

引用在异步操作完成时调用的回调方法。AsyncCallback 引用的事件处理程序包含完成客户端异步任务的程序逻辑。AsyncCallback 使用 IAsyncResult 接口获取异步操作的状态。

下面为例子:

namespace carydemo1

{

    public class AsyncResult : System.IAsyncResult

    {

        public object AsyncState

        {

            get; set;

        }

        System.Threading.WaitHandle asyncWaitHandle = new AutoResetEvent(false);

        public System.Threading.WaitHandle AsyncWaitHandle

        {

            get { return asyncWaitHandle; }

        }

        public bool CompletedSynchronously

        {

            get; set;

        }

        public bool IsCompleted

        {

            get;

            set;

        }

 

        public int Data

        {

            set;get;

        }

    }

 

    class TestClass

    {

        AsyncCallback asyncCallback;

        AsyncResult asyncResult;

        public TestClass()

        {

            asyncCallback = new AsyncCallback(callback);

            asyncResult = new AsyncResult();

        }

        void callback(IAsyncResult asyncResult)

        {

            AsyncResult temp = asyncResult as AsyncResult;

            ((AutoResetEvent)temp.AsyncWaitHandle).Set();

        }

        public AsyncResult AsyncMethod(int value, object asyncState)

        {

            Console.WriteLine("Start...");

            this.asyncResult.AsyncState = asyncState;

            this.asyncResult.Data = value;

            Thread t = new Thread(new ThreadStart(myThread));

            t.Start();

            return this.asyncResult;

        }

        void myThread()

        {

            Console.WriteLine("begin ");

            for (int i = 0; i < 3; i++)

            {

                Console.WriteLine(i);

                asyncResult.Data = asyncResult.Data + i;

                Thread.Sleep(500);

            }

            Console.WriteLine("end...");

            asyncCallback(this.asyncResult);

        }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            TestClass obj = new TestClass();

            AsyncResult r = obj.AsyncMethod(50, null);

            r.AsyncWaitHandle.WaitOne();

            System.Console.WriteLine(r.Data);

            System.Console.WriteLine("完成");

            System.Console.Read();

        }

    }

}