Dezigo
Dezigo

Reputation: 3256

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)
        {

        }
    }
}

Upvotes: 5

Views: 7534

Answers (5)

Lineesh K Mohan
Lineesh K Mohan

Reputation: 1712


Put some synchronization mechanism there

You can use

1.lock(this);

2.monitor.enter(obj); and monitor.exit(obj);

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


    monitor.enter(obj);
      label2.Text = "" + i.ToString();
    monitor.exit(obj);

Upvotes: 0

Jakob M&#246;ll&#229;s
Jakob M&#246;ll&#229;s

Reputation: 4379

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.

Upvotes: 5

DeveloperX
DeveloperX

Reputation: 4683

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)
        {

        }
    }
}

Upvotes: 1

Umesh CHILAKA
Umesh CHILAKA

Reputation: 1466

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

Upvotes: 2

Stecya
Stecya

Reputation: 23276

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

Upvotes: 4

Related Questions