zoukankan      html  css  js  c++  java
  • c#中异步编程

    异步是现实生活中的很多现象的一种抽象。比如分工合作在很多时间段就是异步合作。异步中也一般要涉及委托方法。c#有3种模式的异步编程:异步模式,基于事件的异步模式,基于任务的异步模式(TAP).

    一.  FrameWork 4.0之前的线程世界    

        在.NET FrameWork 4.0之前,如果我们使用线程。一般有以下几种方式:

    • 使用System.Threading.Thread 类,调用实例方法Start()开启一个新线程,调用Abort()方法来提前终止线程。
    • 使用System.Threading.ThreadPool类,调用静态方法QueueUserWorkItem(),将方法放入线程池队列,线程池来控制调用。
    • 使用BeginInvoke,EndInvoke,BeginRead,EnRead,BeginWrite,EndWrite等一系列的异步方法。
    • 使用System.ComponentModel.BackgroundWorker控件,调用实例方法RunWorkerAsync(),开启一个新线程。 

    二.  .Net 传统异步编程概述 

    • 异步编程模型 (APM),在该模型中异步操作由一对 Begin/End 方法(如 FileStream.BeginRead 和 Stream.EndRead)表示。
    • 基于事件的异步模式 (EAP),在该模式中异步操作由名为“操作名称Async”和“操作名称Completed”的方法/事件对(例如 WebClient.DownloadStringAsync 和 WebClient.DownloadStringCompleted)表示。 (EAP 是在 .NET Framework 2.0 版中引入的,在silverlight或者wpf变成中经常用到)。

    三.  Task 的优点以及功能   

    • 在任务启动后,可以随时以任务延续的形式注册回调。
    • 通过使用 ContinueWhenAll 和 ContinueWhenAny 方法或者 WaitAll 方法或 WaitAny 方法,协调多个为了响应 Begin_ 方法而执行的操作。
    • 在同一 Task 对象中封装异步 I/O 绑定和计算绑定操作。
    • 监视 Task 对象的状态。
    • 使用 TaskCompletionSource 将操作的状态封送到 Task 对象。

     第一种 异步模式 

    public class 异步调用
    {
            static void Main()
            {
                Console.WriteLine("===== 异步调用 AsyncInvokeTest =====");
                AddHandler handler = new AddHandler(加法类.Add);
                //IAsyncResult: 异步操作接口(interface)
                //BeginInvoke: 委托(delegate)的一个异步方法的开始
                IAsyncResult result = handler.BeginInvoke(1, 2, null, null);
                Console.WriteLine("继续做别的事情。。。");
                //异步操作返回 EndInvoke方式会阻塞主线程 需要等待异步线程调用完毕 才会执行
                Console.WriteLine(handler.EndInvoke(result));
                Console.ReadKey();
            }
    }
    
    public class 异步回调
    {
            static void Main()
            {
                Console.WriteLine("===== 异步回调 AsyncInvokeTest =====");
                AddHandler handler = new AddHandler(加法类.Add);
                //异步操作接口(注意BeginInvoke方法的不同!)
                IAsyncResult result = handler.BeginInvoke(1,2,new AsyncCallback(回调函数),"AsycState:OK");
                Console.WriteLine("继续做别的事情。。。");
                Console.ReadKey();
            }
     
            static void 回调函数(IAsyncResult result)
            {     
                 //result 是“加法类.Add()方法”的返回值
                //AsyncResult 是IAsyncResult接口的一个实现类,空间:System.Runtime.Remoting.Messaging
                //AsyncDelegate 属性可以强制转换为用户定义的委托的实际类。
                AddHandler handler = (AddHandler)((AsyncResult)result).AsyncDelegate;
              //或者 AddHandler handler=result.AsyncState as AddHandler;
                Console.WriteLine(handler.EndInvoke(result));
                Console.WriteLine(result.AsyncState);
            }
    }

    利用lambda表达式简单写法 (这个很常用。一定要理解和学会。)

                // public delegate string TakesAWhileDelegate(int data1, int data2); 定义一个委托
                TakesAWhileDelegate dl = (a, b) => { return (a + b).ToString(); }; //委托 实例化
                dl.BeginInvoke(1, 12, result => {                     //回调方法 实例化
                  string str=dl.EndInvoke(result);                    //EndInvoke方法取回结果
                  Console.WriteLine("取到异步的结果了result={0}", str);
                }, null);
    

    第二种 基于事件的异步模式

    .net中很多类的方法都定义了同步和异步两种模式,例如WebClient类,就定义了DownloadStringAsync基于事件的异步模式。

                WebClient wc = new WebClient();
                string strUI = "我是主线程中的元素";
                wc.Encoding = Encoding.UTF8;
                //首先实例化 Completed事件。 注意:可以直接访问UI线程中的元素
                // public delegate void DownloadStringCompletedEventHandler(object sender, DownloadStringCompletedEventArgs e);
                wc.DownloadStringCompleted += (sender1, e1) => {   //e1 存放结果
                    Console.WriteLine(strUI);
                    string str = e1.Result;
                    Console.WriteLine(str);
                };
                wc.DownloadStringAsync(new Uri("http://www.baidu.com"));
                Console.WriteLine("继续主线程,不会因为访问网站而阻塞");
    

    第三种 基于任务的异步模式(Task,await,async关键字)

            private void button21_Click(object sender, EventArgs e)
            {
                Console.WriteLine("主线程已经开始了");
                CallerWithAsync();  //调用基于任务的异步方法
                Console.WriteLine("主线程已经结束了");
    
            }
            //创建基于任务的异步方法
            private async void CallerWithAsync() 
            {
                //async(方法修饰符)和await必须成对出现。顺序执行
                string result = await GetAsync("第1个"); //等待 方法执行结果 阻塞线程。编译器把await关键字后的所有代码放进ContinueWith方法的代码块中
                string result2 = await GetAsync("第2个");
                Console.WriteLine("任务第3");
            }
            //通过任务使同步方法异步化
            private Task<string> GetAsync(string name)
            { 
            return Task.Run<string>(() => {
                    Thread.Sleep(2000);
                    Console.WriteLine(name);
                    return name; });
            }
    

      

      

     TASK的用法     请参考这篇文章 

    异步编程新利器

  • 相关阅读:
    ehcache 2.4 即将发布,亮点多多
    2010 年个人回忆与总结
    ehcache 2.4 即将发布,亮点多多
    JBoss Seam 3.0.0.Beta1 发布
    JBoss Seam 3.0.0.Beta1 发布
    jQuery 1.5 正式版如期发布
    jQuery 1.5 正式版如期发布
    Contracts for Java
    2010 年个人回忆与总结
    Contracts for Java
  • 原文地址:https://www.cnblogs.com/crhdyl/p/4892311.html
Copyright © 2011-2022 走看看