如何在不中断主线程的情况下在其创建的其他线程上更新控件? [英] How to update a control on a different thread from which it was created without interrupting the main thread?

查看:75
本文介绍了如何在不中断主线程的情况下在其创建的其他线程上更新控件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C#的新手,我正在开发一个Windows应用程序,其中有一个应该异步执行的方法,该方法的某些任务是更新表单中的某些控件.为此,我使用带有Invoke方法的线程来更新属于该窗体的控件.此表单具有一个启动该线程的按钮和一个应停止该线程的按钮.问题在于,由于使用Invoke方法,主线程(即窗体)被阻塞,直到另一个线程完成,所以我无法单击停止该线程的按钮.

下面是我创建的尝试此程序的程序.它有一个类,可在列表框中添加从1到100的数字.

主程序.

I''m new in C # and I am developing a windows application in which I have a method that should be executed asynchronously, some tasks that this method has is to update some controls in the form. For this I am using a thread with an Invoke method to update the control that belongs to the form. This form has a button that starts this thread and one that should stop it. The problem is that because the use of the Invoke method the main thread, which is the form, is blocked until the other thread to finish, so I can not click on the button that stops the thread.

Below is a program that I created to try this. It has a class that adds the numbers from 1 to 100 in a listbox.

Main program.

private Thread thrAdicionarItens;
        private clcInvoke clcInvokeObject;
 
        private void btnExibir_Click(object sender, EventArgs e) {
            clcInvokeObject = new clcInvoke(lstItens);
            thrAdicionarItens = new Thread(new ThreadStart(clcInvokeObject.AdicionarItens));
            thrAdicionarItens.Start();
        }//End btnExibir_Click()

        private void btnParar_Click(object sender, EventArgs e) {
            try {
                thrAdicionarItens.Abort();
            }
            catch (Exception) {
            }
        }//End btnParar_Click()



类代码




Class code


class clcInvoke
   {
       private ListBox lstItens;

       private delegate void dlgAdicionarItens();

       public clcInvoke(ListBox lstItens) {
           this.lstItens = lstItens;
       }//End clcInvoke()

       public void AdicionarItens() {
           try {
               if (lstItens.InvokeRequired == true)
                   lstItens.BeginInvoke(new dlgAdicionarItens(AdicionarItens));
               else
                   for (byte contador = 1; contador <= 100; contador++) {
                       lstItens.Items.Add(contador.ToString());
                       lstItens.Update();
                       Thread.Sleep(100);
                   }
           }
           catch (Exception) {
           }
       }//End AdicionarItens()

   }//End class clcInvoke




我如何在不使表单锁定到另一个线程完成之前动态地升级表单上的控件的线程?




How do I a thread to upgrade, dynamically, a control on a form without making the form to be locked until the completion of another thread?

推荐答案

中断"是什么意思?调用是将某些处理委托给UI线程的方法.所有委托实例及其调用参数都排队(仅对InvokeBeginInvoke的调用),仅在UI线程上执行.这样,您一旦想使用添加到UI中的某些控件,更新视图等,就将绝对不可避免的添加到UI线程中,这是绝对不可避免的.

您所能做的就是通过预处理与UI线程中与UI控件的方法或属性没有直接关系的所有内容来最大程度地减少工作量.

在您的非UI线程中,您可以节省一些性能:不要调用InvokeRequired-它总是从IO线程返回true,而不是从IO线程调用.

在一个更大"的InvokeBeginInvoke中累积多个调用将无济于事,因为它们始终将数据排队并委派实例.相反,由于不必要的开销,它可能会降低性能.

有关调用的更多详细信息,请参见我过去的回答:
Control.Invoke()与Control.BeginInvoke() [ ^ ],
Treeview Scanner和MD5问题 [用于线程通信的简单阻塞队列和线程间调用 [ ^ ].

—SA
What do your mean "interrupting"? Invocation is the method to delegate some processing to a UI thread. All the delegate instances and their call parameters are queued (be the calls to Invoke or BeginInvoke) to be executed on the UI thread only. In this way, you add some workload to a UI thread, and this is absolutely unavoidable, as soon as you want to use some controls added to the UI, update the view, etc.

All you can do is to minimize the total volume of work by preprocessing of everything not directly related to methods or properties of the UI control in your UI-thread.

In you non-UI thread you can save some performance: don''t call InvokeRequired — it will always return true of called not from the IO thread.

Accumulating of several calls in one "bigger" Invoke or BeginInvoke would not help, because they queue the data and delegate instances anyway. Just the opposite, it can degrade performance due to unwanted overhead.

For more detail in invocation, please see my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also my short Tips & Tricks article for invocation to non-UI thread: Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

—SA


我将构建要添加到线程中的项目列表,将其返回,然后将控件绑定到该列表.对我来说,您正在制作一个调用调用循环,每个调用一个循环,似乎效率不高.
I would build a list of items to add in my thread, return it and then bind the control to the list. You''re making a loop of invoke calls, one per item, which does not seem efficient, to me.


这篇关于如何在不中断主线程的情况下在其创建的其他线程上更新控件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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