zoukankan      html  css  js  c++  java
  • C#中的Invoke和BeginInvoke

    一、Control#Invoke() 和Control#BeginInvoke()

    在非UI线程中调用MessageBox.Show()结果是非模态对话框;
    在UI线程中调用MessageBox.Show()结果是模态对话框。
    也就是说,MessageBox的模态还是非模态控制的是它所在的那个线程!一旦使用MessageBox,它就阻塞了它所在的那个线程。

    在非UI线程中调用System.Forms.Timer#Start方法不管用,在UI线程中才管用。

    以上两个例子引出今日的主角:Control#Invoke()和Control#BeginInvoke()

    • Invoke和BeginInvoke函数使得非UI线程可以方便地把任务放到UI线程中去执行
    • 在UI线程中调用Invoke和BeginInvoke这两个函数是没有意义的,这两个函数只能在非UI线程中调用
      因为它俩的作用就是非UI线程将任务交给UI线程去执行
    • 这两个函数的区别是:Invoke会阻塞非UI线程;BeginInvoke不会阻塞非UI线程

    在编程中,耗时的任务(比如IO,网络请求等)是不允许放在UI线程中的。这一点在一切界面编程中总是成立的。在桌面编程中,从没有库明确禁止耗时任务放在UI线程中。你可以把耗时的任务放在UI线程中,并没有错误,只是难受的是自己。而Android中明确规定UI线程中禁止网络请求,否则会抛出异常。
    当耗时任务结束之后,通常需要更新界面,这时,Invoke和BeginInvoke这两个函数就派上大用了。

    以上两个问题的解决方案:使用Invoke调用MessageBox.Show()和timer.Start().
    this.Invoke(new Action(delegate{}));

    二、委托的Invoke和BeginInvoke

        string haha(string s) {
            return s + s.Length;
        }
        delegate string h(string s);//定义一个函数指针类型
        Haha() {
            h ha = haha;
            IAsyncResult res = ha.BeginInvoke("weidiao", null, null);
            string ans = ha.EndInvoke(res);//此处会阻塞
            Console.WriteLine(ans);
        }
    

    IAsyncResult.IsCompleted属性可以判断任务是否执行完毕。

            IAsyncResult res = ha.BeginInvoke("weidiao", null, null);
            while (res.IsCompleted == false) {
                Console.Write("*");
                Thread.Sleep(500);
            }
            string ans = ha.EndInvoke(res);
    

    IAsyncResult.AsyncWaitHandle属性可以使当前线程(主调线程)等待一段时间。WaitOne的第一个参数表示要等待的毫秒数,在指定时间之内,WaitOne方法将一直等待,直到异步调用完成,并发出通知,WaitOne方法才返回true。当等待指定时间之后,异步调用仍未完成,WaitOne方法返回false,如果指定时间为0,表示不等待,如果为-1,表示永远等待,直到异步调用完成。

            h ha = haha;
            IAsyncResult res = ha.BeginInvoke("weidiao", null, null);
            while (!res.AsyncWaitHandle.WaitOne(500)) {
                Console.Write("*");
            }
            string ans = ha.EndInvoke(res);
            Console.WriteLine(ans);
    

    使用回调函数

    using System;
    using System.Threading;
    using System.Windows.Forms;
    class Haha {
        string haha(string s) {
            Thread.Sleep(3000);
            return s + s.Length;
        }
        delegate string h(string s);
        void callback(IAsyncResult res) {
            Console.Write(ha.EndInvoke(res));
        }
        h ha ;
        Haha() {
            ha = haha;
            IAsyncResult res = ha.BeginInvoke("haha", new AsyncCallback(callback), null);
        }
        static void Main() {
            new Haha();
            Application.Run(new Form());
        }
    }
    
  • 相关阅读:
    移动web性能优化从入门到进阶
    授权保存到相册
    授权通讯地址
    windows putty 链接到 linux 免密码
    my docker note
    docker run -i -t --rm
    Command Not Found
    firewall-cmd 笔记
    vim 插件 Tabularize
    vim :find
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/6344958.html
Copyright © 2011-2022 走看看