从非GUI线程更新GUI->不适用于BeginInvoke() [英] Update GUI from a non-GUI-Thread -> Not working with BeginInvoke()

查看:79
本文介绍了从非GUI线程更新GUI->不适用于BeginInvoke()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用一个button和一个label创建了一个简单的WindowsForms-Application. 如果我单击按钮,则标签应显示1到100000之间的数字.

I have created a simple WindowsForms-Application with one button and one label. If I click the button then the label should display the numbers from 1 to 100000.

但是,如果单击button,则GUI冻结,直到程序计数到100000,然后标签显示100000,GUI停止冻结.

But if I click the button then the GUI freezes till the program counted to 100000 and then the label displays 100000 and the GUI stops freezing.

从1到100000的计数是在新线程(不是GUI线程)中执行的,然后更改我尝试使用BeginInvokelabeltext,但是它不起作用...

The counting from 1 to 100000 is executed in a new thread (not the GUI thread) and then changing of the labeltext I try with BeginInvoke, but it don't works...

using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e) {

            new Thread(DoSomethingExpensive).Start();

        }

        void DoSomethingExpensive() {

            for (int i = 0; i < 100000; i++) {
                this.label1.BeginInvoke((Action)(() => {
                    label1.Text = "" + i;
                    }
                    ));
            }

        }

    }
}

推荐答案

BeginInvoke是异步的.这意味着它将操作排队在UI线程中,然后继续其业务.实际上,在UI线程中排队100,000个操作根本不需要花费很长时间.实际上,与实际执行每个动作相比,它所花费的时间要少得多.这意味着队列最终被所有这些更新文本的请求所淹没.当添加一个新请求(例如,一个重新绘制表单以显示新值的请求,或响应表单上的鼠标单击事件的请求)时,该请求将被放置在队列的末尾,在其他成千上万个其他请求之后.

BeginInvoke is asyncrhonous. This means that it queues the action to take place in the UI thread and then continues on with its business. Queueing up 100,000 actions in the UI thread doesn't actually take long at all. It in fact takes quite a lot less time than actually executing each of those actions. This means that the queue ends up being flooded with all of these requests to update the text. When a new request is added, say, a request to repaint the form to display the new value, or respond to a mouse click event on the form, it is placed at the end of the queue, after those many thousands of other requests.

如果您使用的是Invoke而不是BeginInvoke,则后台工作人员将不会继续在下一个项目排队,直到上一个项目在UI线程中运行完毕为止,以防止其超前于UI线程并泛滥队列.这意味着任何其他UI事件(例如实际重绘屏幕的事件)在队列中最多只能等待一个项目.

If you use Invoke, instead of BeginInvoke, then the background worker won't move on to queue the next item until the previous item has finished running in the UI thread, keeping it from getting ahead of the UI thread and flooding the queue. This means that any other UI events, such as the events to actually repaint the screen, don't have more than at most one item in the queue to wait behind.

这篇关于从非GUI线程更新GUI->不适用于BeginInvoke()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆