Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# multi-threading

I have a problem with C# multi-threading.
Form contents are two buttons and two lables.

If I press on the first button, going looping from 1..to 60000, to update label1. ( It works)

If I press on the second button, going looping from 1..to 6000 to update label2,(and my form is lagged). (is not responding)
Please help!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

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

        private void button1_Click(object sender, EventArgs e)
        {

            Thread thread = new Thread(new ThreadStart(countNumbers));
            thread.IsBackground = true;
            thread.Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Thread thread2 = new Thread(new ThreadStart(countNumbers2));
            thread2.Start();
        }

        public void countNumbers()
        {
            try
            {
                for (int i = 0; i < 60000; i++)
                {
                   this.Invoke((MethodInvoker)delegate()
                   {
                        label2.Text = "" + i.ToString();
                   }
                );
                }
            }
            catch (Exception e)
            {

            }
        }

        public void countNumbers2()
        {
            try
            {
                for (int i = 0; i < 60000; i++)
                {
                    this.Invoke((MethodInvoker)delegate()
                    {
                        label4.Text = "" + i.ToString();
                    }
                 );
                }
            }
            catch (Exception e)
            {

            }
        }



        private void label3_Click(object sender, EventArgs e)
        {

        }
    }
}
like image 561
Dezigo Avatar asked May 30 '11 11:05

Dezigo


4 Answers

Try using a Forms.Timer in the form and poll a value at regular intervals to update the label in a controlled way. Updating the UI the way you do puts way to much load on the system.
A System.Windows.Forms.Timer runs on the GUI thread.

Just make sure to guard the shared resource in some way, this example uses a volatile member to handle thread synchronization.

You do not need the extra Thread.Sleep(10), it is just there to simulate some load.

private volatile int _counter;
private readonly Timer _timer = new System.Windows.Forms.Timer();

public Form1()
{
    InitializeComponent();

    _timer.Tick += TimerTick;
    _timer.Interval = 20;  // ~50 Hz/fps
    _timer.Start();
}

void TimerTick(object sender, EventArgs e)
{
    _label.Text = _counter.ToString();
}

private void Form1_Load(object sender, EventArgs e)
{
    Thread thread = new Thread(CountNumbers) {IsBackground = true};
    thread.Start(); 
}

public void CountNumbers()
{
    for (int i = 0; i < 60000; i++)
    {
        _counter++;
        Thread.Sleep(10);  // <-- Simulated work load
    }
}

Of course, you can easily expand this example to fit your example with two different counters, calculated on separate threads but still using only one Timer to update the entire UI.

like image 94
Jakob Möllås Avatar answered Sep 28 '22 07:09

Jakob Möllås


You end up with lagging because Invoke (switching to another thread) is very expensive operation and you are calling it too frequently

like image 39
Stecya Avatar answered Sep 28 '22 05:09

Stecya


Try giving this.Refresh() or Application.DoEvents() in your loop

like image 29
Umesh CHILAKA Avatar answered Sep 28 '22 05:09

Umesh CHILAKA


Try to use lock statement

  lock (this)
      {
        label2.Text = "" + i.ToString();
       }

you shoud change your code to

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication23
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            Thread thread = new Thread(new ThreadStart(countNumbers));
            thread.IsBackground = true;
            thread.Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Thread thread2 = new Thread(new ThreadStart(countNumbers2));
            thread2.Start();
        }

        public void countNumbers()
        {
            try
            {
                for (int i = 0; i < 60000; i++)
                {
                   this.Invoke((MethodInvoker)delegate()
                   {
                       lock (this)
                       {
                           label2.Text = "" + i.ToString();
                       }
                   }
                );
                }
            }
            catch (Exception e)
            {

            }
        }

        public void countNumbers2()
        {
            try
            {
                for (int i = 0; i < 60000; i++)
                {
                    this.Invoke((MethodInvoker)delegate()
                    {
                        lock (this)
                        {
                            label4.Text = "" + i.ToString();
                        }
                    }
                 );
                }
            }
            catch (Exception e)
            {

            }
        }



        private void label3_Click(object sender, EventArgs e)
        {

        }
    }
}
like image 37
DeveloperX Avatar answered Sep 28 '22 06:09

DeveloperX