C # multithreading

I have a problem with C # multi-threading .
The content of the form consists of two buttons and two tables.

If I press the first button, going into a cycle from 1. to 60000, update the shortcut1. (It works)

If I click on the second button, going from 1. to 6000 to update label2 (and my form is lagging). (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)
        {

        }
    }
}
+5
source share
5 answers

Try using the lock statement

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

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

        }
    }
}
+1
source

Forms.Timer , . , , .
A System.Windows.Forms.Timer .

, - , volatile .

Thread.Sleep(10), .

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
    }
}

, , , .

+5

, Invoke ( ) , .

+4

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

+2
source

Put some synchronization mechanism

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);
0
source

All Articles