• C#委托同步异步说明,并比较control调用Invoke和BeginInvoke的异同


    一.委托的同步和异步:

    1.同步

    使用Invoke调用同步,或直接写fun1("func"),在fun1.Invoke这一步会明显的阻塞线程

    使用:

    static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
    
                //定义一个带返回值的委托
                var fun1 = new Func<string, int>(x =>
                {
                    Thread.Sleep(1000);
                    Console.WriteLine(x);
                    Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
                    return 1;
                });
    
                fun1.Invoke("fun1");
    
                Console.WriteLine("Main");
                Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
                Console.ReadKey();
            }
    

      

     运行结果:

    结果说明:

    同步委托运行在主线程上

    2.异步

    使用BeginInvoke来调用异步,EndInvoke来获取返回值,AsyncCallback定义异步完成回调函数

    使用:

            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
    
                //定义一个带返回值的委托
                var fun1 = new Func<string, int>(x =>
                {
                    Thread.CurrentThread.Name = "fun1";
                    Console.WriteLine(x);
                    Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
                    return 1;
                });
    
                fun1.BeginInvoke("fun1", t =>
                {
                    //var fun2 = t.AsyncState as Func<string, int>;//如果不是lambda表达式需要用该方式获得委托
                    //获取返回值
                    int ret = fun1.EndInvoke(t);
                    Console.WriteLine($"callback return:{ret}");
                    Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
    
                }, null);
    
                Thread.Sleep(1000);
                Console.WriteLine("Main");
                Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
                Console.ReadKey();
            }
    

      

    运行结果:

    结果说明:

    异步委托并不是运行在主线程上,而是运行在独立的线程上,是异步执行的

     二.control的Invoke和BeginInvoke

    1.Invoke

    使用:

            private void button1_Click(object sender, EventArgs e)
            {
                Thread.CurrentThread.Name = "UIThread";
                this.Invoke(new Action(() =>
                {
                    Thread.Sleep(5000);
                    Debug.WriteLine($"Invoke ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
                }));
    
                Debug.WriteLine($"Main ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
            }
    

      运行结果:

    结果说明:

    可以明显的感到Invoke阻塞了界面5s后,才执行后面的代码

    Invoke内的委托在UI线程上执行,是同步的

     2.BeginInvoke

    使用:

            private void button1_Click(object sender, EventArgs e)
            {
                Thread.CurrentThread.Name = "UIThread";
    
                this.BeginInvoke(new Action(() =>
                {
                    Debug.WriteLine($"BeginInvoke ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
                }));
    
                Debug.WriteLine($"Main ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
                Thread.Sleep(5000);
            }
    

      

      运行结果:

    结果说明:

    可以明显看到界面卡了5s后,才先执行的BeginInvoke内的委托

    结论:BeginInvoke内的委托在UI线程上执行,并不是异步,只是放在UI线程中最后执行。

     三.结论

    delegate.Invoke 运行在主线程上,同步执行,并立即执行,会阻塞主线程
    delegate.BeginInvoke 运行在独立线程上,异步执行, 并立即执行,不会阻塞主线程
    Control.Invoke 运行在UI线程上,同步执行,并立即执行,会阻塞UI线程
    Control.BeginInvoke 运行在UI线程上,不是异步执行,等UI线程其他操作完成才执行,会阻塞UI线程
  • 相关阅读:
    document.body.appendChild 的问题
    页面不刷新,表单提交到弹出窗口或Iframe
    您对无法重新创建的表进行了更改或者启用了 阻止保存要求创建表的更改
    转载:兼容各类浏览器的CSS Hack技巧
    sql server 代理权限问题
    配置SQL用户访问指定表,指定列
    关于嵌入式系统的启动(装载)
    centos 中安装g++
    嵌入式中利用ftp实现宿主机与目标机通信
    TQ2440加载Hello world驱动模块
  • 原文地址:https://www.cnblogs.com/yaosj/p/10616192.html
Copyright © 2020-2023  润新知