C#中的异步调用及异步设计模式(一)

 

近期项目中使用了不少异步操作,关于“异步”做个总结。总结的内容大部分都来自于MSDN,还有一些自己的心得。

关于“异步”的使用可分为:使用层面和类库设计层面,细分如下:

一、使用异步方式调用同步方法(使用层面)。

二、使用 IAsyncResult 调用异步方法(使用层面)。

三、基于 IAsyncResult 的异步设计模式(设计层面)。

四、基于事件的异步模式(设计层面)。

关于上述异步编程的几个方面,下面分别做以详述。

一、使用异步方式调用同步方法(使用层面)

.NET Framework 允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义 BeginInvoke 和 EndInvoke 方法。BeginInvoke 方法可启动异步调用,EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。

该调用方式是使用委托进行异步调用,其实质是:调用“BeginInvoke”方法,公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行,该目标方法是在线程池线程运行的。

在异步调用启动后,在等待异步调用结果的时候,可以进行以下四种方法。

·                     进行某些操作,然后调用 EndInvoke 一直阻止到调用完成。

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain
    {
        public static void Main()
        {
            // The asynchronous method puts the thread id here.
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke(3000,
                out threadId, null, null);

            Thread.Sleep(0);
            Console.WriteLine("Main thread {0} does some work.",
                Thread.CurrentThread.ManagedThreadId);

            // 调用此方法将会一直等待异步操作完成,并阻塞当前线程。
            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}


 

·                     进行某些操作,然后使用 IAsyncResult..::.AsyncWaitHandle 属性获取 WaitHandle,使用它的 WaitOne 方法(该方法可以设置一个超时时间)一直阻止执行直到发出 WaitHandle 信号,然后调用 EndInvoke。

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain
    {
        static void Main()
        {
            // The asynchronous method puts the thread id here.
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke(3000,
                out threadId, null, null);

            Thread.Sleep(0);
            Console.WriteLine("Main thread {0} does some work.",
                Thread.CurrentThread.ManagedThreadId);

            // 调用此方法将会一直等待异步操作完成,并阻塞当前线程。
            result.AsyncWaitHandle.WaitOne();

            // Perform additional processing here.
            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}


 

·                     进行某些操作,然后轮询由 BeginInvoke 返回的 IAsyncResult,确定异步调用何时完成,然后调用 EndInvoke。

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain
    {
        static void Main()
        {
            // The asynchronous method puts the thread id here.
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke(3000,
                out threadId, null, null);

            // 等待结果返回
            while (result.IsCompleted == false)
            {
                Thread.Sleep(10);
            }

            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}


 

·                     将用于回调方法的委托传递给 BeginInvoke。异步调用完成后,将在 ThreadPool 线程上执行该方法。该回调方法将调用 EndInvoke。注意:该回调函数的执行是在另外一个线程上。

 

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        // Asynchronous method puts the thread id here.
        private static int threadId;

        static void Main() {
            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

            // Initiate the asychronous call.  Include an AsyncCallback
            // delegate representing the callback method, and the data
            // needed to call EndInvoke.
            IAsyncResult result = caller.BeginInvoke(3000,
                out threadId, 
                new AsyncCallback(CallbackMethod),
                caller );

            Console.WriteLine("Press Enter to close application.");
            Console.ReadLine();
        }

        // Callback method must have the same signature as the
        // AsyncCallback delegate.
        static void CallbackMethod(IAsyncResult ar) 
        {
            // Retrieve the delegate.
            AsyncMethodCaller caller = (AsyncMethodCaller) ar.AsyncState;

            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, ar);

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}


二、使用 IAsyncResult 调用异步方法(使用层面)

.NET Framework 的许多方面都支持异步编程功能,这些方面包括:

·                     文件 IO、流 IO、套接字 IO。

·                     网络。

·                     远程处理信道(HTTP、TCP)和代理。

·                     使用 ASP.NET 创建的 XML Web services。

·                     ASP.NET Web 窗体。

·                     使用 MessageQueue 类的消息队列。

这些已经实现了异步操作的类或组件,可以直接调用其异步方法(以Begin和End开头)。调用异步方法后等待结果可以参考“异步调用同步方法”的处理。

 

三、基于 IAsyncResult 的异步设计模式(设计层面)

待续...

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值