zoukankan      html  css  js  c++  java
  • 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线程
  • 相关阅读:
    [导入]C#中将字符串转成 Base64 编码
    [导入]GridView中实现并列排名的例子
    VB.net编程中可能用到的边边角角(二) —— 取Mac地址、取某String的MD5值、多线程、RAR压缩、ADOX生成数据库、加载工程内的Form、一个滚动条控制两个DataGridView
    (转)Setup Factory 打包工具部分功能代码解析
    (转)SQL 优化原则
    VB.net编程中可能用到的边边角角(一) —— 反射添加Form、向Excel中写值
    自写的简单屏蔽特定字符的TextBox和数字TextBox
    spring import resource 文件后bean找不到问题解决
    mysql插入记录后获取插入数据的id值
    cookie+memcached实现单点登陆
  • 原文地址:https://www.cnblogs.com/yaosj/p/10616192.html
Copyright © 2011-2022 走看看