zoukankan      html  css  js  c++  java
  • 第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待。

    一. 再谈委托

    1. 委托是一个关键字为delegate的自定义类型,通过委托可以把方法以参数的形式传递给另外一个方法,实现插件式的开发模式;

        同时调用委托的时候,委托所包含的所有方法都会被实现。

    2. 委托的发展历史:new实例化传递方法→直接等于方法名→delegate匿名方法→省略delegate→省略括号中的参数→当只有一个参数省略小括号

              →当方法体只有一行,省略大括号

     (详见:http://www.cnblogs.com/yaopengfei/p/6959141.html)

    3:常用的Action委托和Func委托

      A. Action<>委托,无返回值,至少有一个参数的委托

      B. Func<>委托,有返回值,可以无参数的委托(当然也可以有参数)

      C. Action委托,无参数无返回值的委托 

    二. 委托的调用

    委托的调用分为两种:

      A. 同步调用:Invoke方法,方法参数为函数的参数。

      B. 异步调用:BeginInvoke方法。

    其中无论是哪类调用,都有两类写法:

      ①:利用Action<>(或Func<>)内置委托,调用的时候赋值。

      ②:利用Action委托,直接赋值,然后调用。

     1         /// <summary>
     2         /// 执行动作:耗时而已
     3         /// </summary>
     4         private void TestThread2(string threadName1, string threadName2)
     5         {
     6             Console.WriteLine("线程开始:线程名为:{2}和{3},当前线程的id为:{0},当前时间为:{1},", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName1, threadName2);
     7             long sum = 0;
     8             for (int i = 1; i < 999999999; i++)
     9             {
    10                 sum += i;
    11             }
    12             Console.WriteLine("线程结束:线程名为:{2}和{3},当前线程的id为::{0},当前时间为:{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName1, threadName2);
    13         }

     

     

    三. 深入剖析BeginInvoke方法

       首先需要明确,该方法参数个数不定, 最后两个参数含义固定,如果不使用的话,需要赋值null;该方法最少两个参数,即方法无参数,这种情况下BeginInvoke中只有两个参数。此外,赋值的方法有几个参数,BeginInvoke中从左开始,新增几个参数。

      ①. 倒数第二个参数:是有一个参数值无返回值的委托,它代表的含义为,该线程执行完毕后的回调。

      ②. 倒数第一个参数:向倒数第二个参数(即回调)中传值,需要用AsyncState来接受。

      ③. 其它参数:即为赋值方法的参数。

    注:BeginInvoke的返回值等价于异步回调中的t。

     1   private void button13_Click(object sender, EventArgs e)
     2         {
     3             Stopwatch watch = new Stopwatch();
     4             watch.Start();
     5             Console.WriteLine("----------------- button1_Click 开始 主线程id为:{0}  --------------------------", Thread.CurrentThread.ManagedThreadId);
     6 
     7             Action<string> myFunc = this.TestThread;
     8             IAsyncResult asyncResult = null;
     9             //参数说明:前面几个参数都是方法的参数值,倒数第二个为异步调用的回调函数,倒数第一个为传给回调函数的参数
    10             for (int i = 0; i < 1; i++)
    11             {
    12                 string name = string.Format("button1_Click{0}", i);
    13                 asyncResult = myFunc.BeginInvoke(name, t =>
    14                    {
    15                        Console.WriteLine("我是线程{0}的回调", Thread.CurrentThread.ManagedThreadId);
    16                        //用 t.AsyncState 来获取回调传进来的参数
    17                        Console.WriteLine("传进来的参数为:{0}", t.AsyncState);
    18 
    19                        //测试一下异步返回值的结果
    20                        Console.WriteLine("异步返回值的结果:{0}", t.Equals(asyncResult));
    21                    }, "maru");
    22             }
    23 
    24             watch.Stop();
    25             Console.WriteLine("----------------- button1_Click 结束 主线程id为:{0}  总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
    26 
    27         }

    结果:

     

    四. 线程等待的三种方式

    1. asyncResult.IsCompleted属性,该方式会存在时间上的误差。

    2. WaitOne方法,可以控制一直等待or超时不再等待。

    3. EndInvoke方法,官方推荐的线程等待的方式。

    以上三种方式的局限性:批量线程等待的时候,不灵活,需要for循环了。

     1   private void button14_Click(object sender, EventArgs e)
     2         {
     3             Stopwatch watch = new Stopwatch();
     4             watch.Start();
     5             Console.WriteLine("----------------- button1_Click 开始 主线程id为:{0}  --------------------------", Thread.CurrentThread.ManagedThreadId);
     6 
     7             IAsyncResult asyncResult = null;
     8             Action<string> myFunc = this.TestThread;
     9             string name = string.Format("button1_Click{0}", 111);
    10             asyncResult = myFunc.BeginInvoke(name, t =>
    11              {
    12                  Console.WriteLine("我是线程{0}的回调", Thread.CurrentThread.ManagedThreadId);
    13                  //用 t.AsyncState 来获取回调传进来的参数
    14                  Console.WriteLine("传进来的参数为:{0}", t.AsyncState);
    15              }, "maru");
    16 
    17             //等待的方式1:会有时间上的误差
    18             //while (!asyncResult.IsCompleted)
    19             //{
    20             //    Console.WriteLine("正在等待中");
    21             //}
    22 
    23             // 等待的方式二:
    24             //asyncResult.AsyncWaitHandle.WaitOne();//一直等待
    25             //asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待
    26             //asyncResult.AsyncWaitHandle.WaitOne(1000);//等待1000毫秒,超时就不等待了
    27 
    28             //等待的方式三:
    29             myFunc.EndInvoke(asyncResult);
    30 
    31             watch.Stop();
    32             Console.WriteLine("----------------- button1_Click 结束 主线程id为:{0}  总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
    33 
    34         }

    下面是多个线程等待的情况:

     1   private void button15_Click(object sender, EventArgs e)
     2         {
     3             Stopwatch watch = new Stopwatch();
     4             watch.Start();
     5             Console.WriteLine("----------------- button1_Click 开始 主线程id为:{0}  --------------------------", Thread.CurrentThread.ManagedThreadId);
     6 
     7             List<IAsyncResult> list = new List<IAsyncResult>();
     8 
     9             for (int i = 0; i < 5; i++)
    10             {
    11                 string name = string.Format("button1_Click{0}", i);
    12                 Action myFunc = () =>
    13                 {
    14                     TestThread2(name, name);
    15                 };
    16                 var asyncResult = myFunc.BeginInvoke(null, null);
    17                 list.Add(asyncResult);
    18             }
    19 
    20             //下面是线程等待
    21             foreach (var item in list)
    22             {
    23                 item.AsyncWaitHandle.WaitOne(-1);
    24             }
    25 
    26             watch.Stop();
    27             Console.WriteLine("----------------- button1_Click 结束 主线程id为:{0}  总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
    28         }

    结果:

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    topcoder srm 320 div1
    topcoder srm 325 div1
    topcoder srm 330 div1
    topcoder srm 335 div1
    topcoder srm 340 div1
    topcoder srm 300 div1
    topcoder srm 305 div1
    topcoder srm 310 div1
    topcoder srm 315 div1
    如何统计iOS产品不同渠道的下载量?
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/8094512.html
Copyright © 2011-2022 走看看