C#多线程

时间:2011-05-30 11:47:21

标签: c# .net multithreading winforms

我遇到了 C#多线程的问题 表格内容为两个按钮和两个标签。

如果我按下第一个按钮,从1..00到60000循环,更新label1。 (它有效)

如果我按下第二个按钮,从1到6000循环以更新label2,(并且我的表格滞后)。 (没有回应)
请帮忙!

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 个答案:

答案 0 :(得分:5)

尝试在表单中使用Forms.Timer并定期轮询值以受控方式更新标签。以您的方式更新UI会使方式加载到系统上 在GUI线程上运行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
    }
}

当然,您可以轻松扩展此示例以使您的示例适合两个不同的计数器,这些计数器在单独的线程上计算,但仍然只使用一个Timer来更新整个UI。

答案 1 :(得分:4)

你最终会陷入困境,因为Invoke(切换到另一个线程)是非常昂贵的操作而你太频繁地调用它

答案 2 :(得分:2)

尝试在循环中提供this.Refresh()Application.DoEvents()

答案 3 :(得分:1)

尝试使用锁定语句

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

您应该将代码更改为

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

        }
    }
}

答案 4 :(得分:0)


在那里设置一些同步机制

您可以使用

1.lock(本);

2.monitor.enter(OBJ);和monitor.exit(obj);

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


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