• 委托和多线程(一)


             定义:委托是一个类型安全的对象,它指向程序中另一个以后会被调用的方法(或多个方法)。通俗的说,委托是一个可以引用方法的对象,当创建一个委托,也就创建一个引用方法的对象,进而就可以调用那个方法,即委托可以调用它所指的方法。

    委托的试用步骤:

    1、定义委托:权限修饰符   delegate   返回值     委托名 (参数);

    2、声明委托:  委托名 委托对象;

    3、将对象与委方法绑定(可以绑定一个方法或者多个方法): 委托对象  = new 委托名(需要绑定的方法名称);

    4、使用委托调用方法:委托实例名(参数);

    Ps:1、委托和委托绑定的方法需要相同的参数(参数类型和个数都要相同)和返回值;

            2、委托可以调用多个方法,委托对象可以维护可调用方法的列表;即多路广播,简称:多播;

            3、使用+= 添加绑定方法,-=释放绑定方法;delegate委托可以不带参数,支持最大23个参数;可以没有返回值,也可以带返回值;

    委托其中常见的写法有:

    1、实例化委托并调用:委托名  委托实例 = new 委托名(委托方法);委托实例(参数);

    2、实例化委托并调用 简写委托名  委托实例 = 委托的方法 ;委托实例(参数);

    3、实例化委托并调用 匿名委托:委托名   委托实例 = delegate(参数){待调用的方法体};委托名(参数);

    4、实例化委托并调用 lambda表达式写法:委托名  委托实例 = ((参数1,参数2,参数3,参数4,...参数n)=>{待调用的方法体});委托实例(参数1,参数2,参数3,...参数n);

    5、在.NET 2.0开始 ,出现Func<in T,out TResult> 和Action<in T>

         Func至少0个参数,至多16个参数,必须有返回值

         Action至少0个参数,至多16个参数,无返回值。

         Func<参数1,参数2,...参数n,返回值> 委托实例 = ((参数1,参数2,。。。参数n)=>{带返回值的方法体});

         返回值 = 委托实例(参数1,参数2,。。。参数n);

         Action<参数> 委托实例 = ((参数)=>{待执行的方法体});委托实例(参数);

         Predicate<T>表示定义一组条件并确定指定对象是否符合这些条件的方法,返回值始终为bool类型

          申明的原型:  public delegate bool Predicate<in T>(T obj)  由于比较陌生;所以下面给一个事例:

          

    1 public bool Match(int val)
    2 {
    3     return val > 60;
    4 }
    5     
    6 Predicate<int> t = new Predicate<int>(Match);   //定义一个比较委托
    7 int[] arr = { 13, 45, 26, 98, 3, 56, 72, 24 };            
    8 int first = Array.Find(arr, t);                 //找到数组中大于60的第一个元素

      下面陆续介绍:

    1、Invoke

    2、BeginInvoke,EndInvoke

    3、Thread

    4、线程池

    5、线程同步

    6、死锁

    7、线程同步的几种方法

    8、在线程中访问GUI组件

    Invoke:

          Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托。

          Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句柄所在线程上异步执行指定委托。

     msdn说明:

          控件上的大多数方法只能从创建控件的线程调用。 如果已经创建控件的句柄,则除了 InvokeRequired 属性以外,控件上还有四个可以从任何线程上安全调用的方法,它们是:InvokeBeginInvokeEndInvoke 和 CreateGraphics。 在后台线程上创建控件的句柄之前调用 CreateGraphics 可能会导致非法的跨线程调用。 对于所有其他方法调用,则应使用调用 (invoke) 方法之一封送对控件的线程的调用。 调用方法始终在控件的线程上调用自己的回调。

          主线程调用Invoke:

    1       public void TestInvoke()
    2         {
    3             listBox1.Items.Add("----Add------
    ");
    4             listBox1.Invoke(new Action(() => { listBox1.Items.Add("Incoke"); }));
    5             Thread.Sleep(1000);
    6             listBox1.Items.Add("---End-----");
    7         }

         主线程调用BeginInvoke:

    1        public void TestInvoke()
    2         {
    3             listBox1.Items.Add("----Add------
    ");
    4             var b = listBox1.BeginInvoke(new Action(() => { listBox1.Items.Add("BrginInvoke"); }));
    5             Thread.Sleep(1000);
    6             listBox1.Items.Add("---End-----");
    7         }

    只有当调用BeginInvoke的线程结束后,才执行它的内容。

    不过有两种情况下,它会马上执行;1、使用EndInvoke,检索由传递的 IAsyncResult 表示的异步操作的返回值。2、同一个控件调用Invoke时,会马上执行先前的BeginInvoke

    1、

     1  public void TestInvoke()
     2         {
     3             listBox1.Items.Add("----Add------
    ");
     4             var b = listBox1.BeginInvoke(new Action(() =>
     5             {
     6                 Thread.Sleep(1000);
     7                 listBox1.Items.Add("BrginInvoke");
     8             }));
     9             listBox1.EndInvoke(b);
    10             listBox1.Items.Add("---End-----");
    11         }

    2.

     1  private void TestBeginInvokeInvoke()
     2         {
     3             listBox1.Items.Add("--begin--");
     4             listBox1.BeginInvoke(new Action(() =>
     5                 {
     6                     Thread.Sleep(1000);
     7                     listBox1.Items.Add("BeginInvoke");
     8                 }));
     9             listBox1.Invoke(new Action(() =>
    10                 {
    11                     listBox1.Items.Add("Invoke");
    12                 }));
    13             listBox1.Items.Add("--end--");
    14         }

     注:在主线程中直接调用Invoke、BeginInvoke、EndInvoke都会造成阻塞。所以应该利用副线程(支线线程)调用

    • Invoke的委托在主线程中执行
    • Invoke在支线程中调用也会阻塞主线程
    • Invoke还会阻塞支线程
  • 相关阅读:
    剑指offer(4)
    剑指offer(3)
    剑指offer(2)
    剑指offer(1)
    (二)Wireshark的实用表格
    RedHat Enterprise Linux 6.4使用yum安装出现This system is not registered to Red Hat Subscription Management
    Android:简单的图片浏览器
    rpm和yum
    良心推荐!GitHub14400颗星!非常不错的机器学习指南
    Python中免验证跳转到内容页的实例代码
  • 原文地址:https://www.cnblogs.com/QQ931697811/p/4351320.html
Copyright © 2020-2023  润新知