Click here to Skip to main content
16,016,744 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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.

C#
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


C#
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?

[Edit - Unchecked the "Treat my content as plain text, not as HTML" checkbox so the code blocks work]
Posted
Updated 7-Feb-12 7:57am
v2

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
 
Share this answer
 
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.
 
Share this answer
 
Comments
Edson Rodrigues da Silva 7-Feb-12 11:46am    
My application will receive data from serial port and these data should be displayed constantly in form, so I call the update method on each loop. And I need this method to be done in a thread so that I can have a button that stops the communication with the serial port anytime.
This example is just for me to learn to do it.
How can I do this without interrupting the main program?
Christian Graus 7-Feb-12 12:04pm    
Your best bet is probably then to build a list of a certain number of items and THEN do an update, so your thread is not constantly hammering the main one.
Sergey Alexandrovich Kryukov 7-Feb-12 17:38pm    
Cristian, unfortunately this trick cannot really help, by the reasons I explain in my answer -- please see.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900