繁体   English   中英

没有MethodInvoker,Control.BeginInvoke()无法正常工作-但是为什么呢?

[英]Control.BeginInvoke() not working without MethodInvoker - But why?

Ich有一个小的WinForms程序,其中包含1 Button和1 Textbox。 如果我单击按钮,则程序从1计数到100000,并在每一步中以毫秒为单位显示当前时间。 countingloop在单独的线程中运行。

                public partial class Form1 : Form {

                   public delegate void myDelegate();
                   public myDelegate mydelegate;

                    public Form1() {
                        InitializeComponent();

                        mydelegate = new myDelegate(b);
                    }

                    private void button1_Click(object sender, EventArgs e) {
                        button2.Focus();

                        Thread t = new Thread(a);
                        t.Start();
                    }

                    private void Form1_KeyDown(object sender, KeyEventArgs e) {
                        Console.WriteLine(e.KeyCode);
                    }

                    public void a() {
                        for (int i = 0; i < 100000; i++) {
                            textBox1.BeginInvoke(mydelegate);



                        }
                    }

                    public void b() {
                        textBox1.Text = GetCurrentMilli().ToString();
                        textBox1.Refresh();
                    }

                    public static double GetCurrentMilli() {
                        DateTime Jan1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                        TimeSpan javaSpan = DateTime.UtcNow - Jan1970;
                        return javaSpan.TotalMilliseconds;
                    }

                }

如果我运行此程序,程序将运行,但gui会冻结直到循环完成。 但为什么? 我已经致电BeginInvoke ?!

如果我更换

                textBox1.BeginInvoke(mydelegate);

                      textBox1.Invoke(new MethodInvoker(b));

那么它就可以正常工作,没有任何冻结或问题。 但为什么?

当您调用BeginInvoke您计划进行一次UI更新,然后继续执行程序而不等待该UI更新发生。 当您几次执行此操作时,您就可以了,但是问题是您一次要发送100,000个请求,这将需要UI花费一些时间来处理所有这些请求,并且那时将无法进行其他操作,因为任何新的UI更新都将移至该行的末尾,并且只有在其他请求完成后才能执行。

尽管有一些方法可以使您的一般方法保持不变,并尝试让其他操作切入行列,但正确的方法是首先避免出现问题。 您无需一次向单个文本框发送100,000个更新。

如果您希望文本框具有时钟的外观(在时钟中滴答作响),那么Timer将是完成此项工作的好工具; 您可以处理“ Tick事件,以每秒,每刻四分之一秒或其他“人工时间”间隔更新文本框。

如果您的想法是使用一些长期运行的操作来更新UI,那么您只想确保您不会经常更新进度。 例如,循环的每几十次更新进度,而不是每一次更新一次。

您可能需要在两者之间调用UpdateLayout ,不确定是否需要调用它以防止跨线程异常

public void a() {
    for (int i = 0; i < 100000; i++) {
        textBox1.BeginInvoke(mydelegate);
        textBox1.UpdateLayout();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM