Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have two buttons startbtn and stopbtn, a combobox and a listbox. The combobox collection items are "TRUE" & "FALSE". below is the,

C#
private void startbtn_Click(object sender, EventArgs e)
        {
            int i = 0;
            while (comboBox1.Text == "TRUE")
            {
                
                i = i + 1;
                listBox1.Items.Add(i.ToString());
            }
        }

C#
private void stopbtn_Click(object sender, EventArgs e)
        {
            comboBox1.Text = "FALSE";
        }


The thing is we all know that while the above code is executing
1. we cannot change the combobox text from "TRUE" to "FALSE"
2. we cannot click on stopbtn to terminate the process.
3. Listbox1 will not get updated at each loop time until the process is completed (unless i am using a backgrounder class).

how to use threading to overcome these 3 issues? do we need to thread each controls and event handlers seperately? i can't quite understand how thread multiple event handlers. I am learning the threading concept for my upcoming project. Here is where i have to start. Please help me to understand

What I have tried:

http://www.c-sharpcorner.com/article/introduction-to-multithreading-in-C-Sharp/
Posted
Updated 28-Jul-16 3:26am
Comments
BillWoodruff 26-Jul-16 23:59pm    
Please do search CodeProject and read some of the articles on threading here, and read some of the related questions right in front you under the orange "Related Questions" banner.
Member 12226114 27-Jul-16 1:10am    
Okay. Thank you

Here is a solution using Windows Forms. I tried to stay as close to your code as possible, although Foothill's solution is better in my opinion, and you could use it by changing a single line of code:

C#
Dispatcher.Invoke(() => listBox1.Items.Add(i.ToString()));


Should be changed to:

C#
this.Invoke((MethodInvoker)(() => listBox1.Items.Add(i.ToString())));


Yes, we're using lambda expressions. If you're not familiar with them, you should read up on lambda expressions and Anonymous Methods here, and here.

Here's my solution (keeping as close to your code as possible):
C#
private void startbtn_Click(object sender, EventArgs e)
{
    String comboBox1Text = "";

    this.Invoke((MethodInvoker)(() => comboBox1Text = comboBox1.Text));
    new System.Threading.Thread(() =>
    {
        int i = 0;
        while (comboBox1Text.Equals("TRUE"))
        {
            i = i + 1;
            this.Invoke((MethodInvoker)(() => 
            { 
                listBox1.Items.Add(i.ToString());
                comboBox1Text = comboBox1.Text;
            }));
        }
    }).Start();
}

private void stopbtn_Click(object sender, EventArgs e)
{
    comboBox1.Text = "FALSE";
}


This works - I tested it. Let me explain a little about why it works.

As Griff said above, you can only update user interface (UI) elements from the thread that created them. In Windows forms, all controls "know" which thread created them, and even a Form is a control. You can ask a control if you are accessing it from the thread that created it using control.invokeRequired (returns a bool). If it returns true, then you need to "Invoke" the control, or schedule code to run on the UI thread. You do this by calling control.Invoke(). Take a minute, and read up on what control.invoke does here.

There are many different ways to use control.invoke(), but the one I used in this example - while maybe not the best (I usually set up a helper function to handle UI updates and pass it code in a lambda expression. It makes your code clearer / more readable), works in this example.

If I missed anything,or you have any questions, please feel free to ask.

- Pete
 
Share this answer
 
v3
Comments
Foothill 28-Jul-16 9:55am    
Got my vote of 5.
pdoxtader 28-Jul-16 10:14am    
Thanks man.
Member 12226114 31-Jul-16 21:57pm    
Thanks a lot for your solution & explanation. Got clarified
Threading isn't difficult to organise, but that code would need modification, because you can't access controls except on the thread on which they were created - the UI thread. So your loop termination / thread exit test cannot involve the combobox directly. Unfortunately, that also applies to the ListBox as well - it needs to be Invoked onto teh UI thread in order to add your items.
Having said that, it's not difficult to do:
C#
private bool endTheLoop = false;
private void startbtn_Click(object sender, EventArgs e)
    {
    endTheLoop = false;
    BackgroundWorker work = new BackgroundWorker();
    work.DoWork += work_DoWork;
    work.RunWorkerAsync();
    }

void work_DoWork(object sender, DoWorkEventArgs e)
    {
    int i = 0;
    while (!endTheLoop)
        {

        i = i + 1;
        listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add(i.ToString()); });
        }

    }
private void stopbtn_Click(object sender, EventArgs e)
    {
    endTheLoop = true;
    }
 
Share this answer
 
If you want to take advantage of lambda expressions, this might also work for you.
Note: this was written to use with WPF
C#
public bool Stop { get; set; }
private void startbtn_Click(object sender, EventArgs e)
{
  Thread worker = new Thread(() =>
   {
     int i = 0;

     while (!Stop)
     {
       Dispatcher.Invoke(() => listBox1.Items.Add(i.ToString()));
       ++i;
     }
   }
  );

  worker.Start();
}
private void stopbtn_Click(object sender, EventArgs e)
{
  Stop = true;
}
 
Share this answer
 
Comments
pdoxtader 27-Jul-16 16:57pm    
Yes, this will work. But you have rewritten it so completely that unless you understand what a lambda expression is, and have a grasp on what the Dispatcher does in WPF you just won't understand it. And lets be honest here - this guy doesn't understand basic threading concepts and didn't know that you can only update UI elements from the UI thread before posting this question.

I bet I could find a way to throw a ternary expression in there to really confuse him... Lol. But maybe instead one of us should actually explain it to the guy. If no one has mercy on him, maybe I'll do it myself later.
Member 12226114 27-Jul-16 23:53pm    
Sorry for delayed response. I was trying on my own solution. Eventually, I understand that windows form controls needs to be invoked for using with the thread.
Member 12226114 27-Jul-16 23:56pm    
Anyway still am unable to find the solution & scratching my head. I will try foothill's solution. Because I already accomplished the task using background worker, what i required now is only by threading.
pdoxtader 28-Jul-16 9:38am    
I posted a solution and an explanation. hope that helps.

- Pete
Member 12226114 27-Jul-16 23:58pm    
Also, it would be helpful for me if you guys tell me how to invoke the winform controls into MYthread.

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