c# - C# :Cross-thread operation not valid: Control 'lblp4' accessed from a Cross-thread operation not valid 中的线程异常错误

标签 c# multithreading

首先,对不起我的英语语言不好,我是初学者程序员。在我的项目中,我使用线程类,但完成后我看到了这个异常:

Cross-thread operation not valid: Control 'lblp4' accessed from a thread other than the thread it was created on.

在我的项目中,我从 Form1 类中的 Philosopher 类中调用了 5 个函数 Synchronize:

哲学家类:

namespace AZsys 
{
class Philosopher 
{
    public Int32 i;

    public bool e, th;
    public Philosopher()
    {

    }
    public void main()
    {
        lock (AZsys.Program.frm.locker)
        {
            while (true)
            {
                if (i < 0 || i > 4)
                {
                    System.Windows.Forms.MessageBox.Show("error");
                    break;
                }
                else
                {
                    think();
                    AZsys.Program.frm.chopstick[i].WaitOne();
                    AZsys.Program.frm.chopstick[(i + 1) % 5].WaitOne();
                    eat();
                    AZsys.Program.frm.chopstick[(i + 1) % 5].Release();
                    AZsys.Program.frm.chopstick[i].Release();
                }
            }
        }
        Thread.Sleep(100);
    }
    private void eat()
    {
            switch (i)
            {
                case 1:
                    AZsys.Program.frm.lblp1.Text = "Eating...";
                    break;
                case 2:
                    AZsys.Program.frm.lblp2.Text = "Eating...";
                    break;
                case 3:
                    AZsys.Program.frm.lblp3.Text = "Eating...";
                    break;
                case 4:
                    AZsys.Program.frm.lblp4.Text = "Eating...";
                    break;
                case 5:
                    AZsys.Program.frm.lblp5.Text = "Eating...";
                    break;
            }
        e = true;

        for (int j = 0; j < 992; j++)
        {
            if (j % 8 == 0)
                e = true;
        }
        e = false;
    }

    private void think()
    {
            switch (i)
            {
                case 1:
                    AZsys.Program.frm.lblp1.Text = "Thinking..."+Thread.CurrentThread.Name.ToString();
                    break;
                case 2:
                    AZsys.Program.frm.lblp2.Text = "Thinking..."+Thread.CurrentThread.Name.ToString();
                    break;
                case 3:
                    AZsys.Program.frm.lblp3.Text = "Thinking..."+Thread.CurrentThread.Name.ToString();
                    break;
                case 4:
                    AZsys.Program.frm.lblp4.Text = "Thinking..."+Thread.CurrentThread.Name.ToString();
                    break;
                case 5:
                    AZsys.Program.frm.lblp5.Text = "Thinking..." + Thread.CurrentThread.Name.ToString();
                    break;
            }

        th = true;

        for (int j = 0; j < 9924; j++)
        {
            if (j % 8 == 0)
                th = true;
        }
        th = false;
    }
}

即使在这段代码中,我也使用了锁(locker)但不起作用!!!

Form1 类:

   public partial class Form1 : Form
{
    public  Semaphore[] chopstick;
    public  object locker;

    private Philosopher ph1;
    private Philosopher ph2;
    private Philosopher ph3;
    private Philosopher ph4;
    private Philosopher ph5;

    public Form1()
    {
        InitializeComponent();
        chopstick = new Semaphore[5];



    }

    private void Form1_Load(object sender, EventArgs e)
    {
        locker = new object();
        ph1 = new Philosopher();
        ph1.i = 1;
        ph2 = new Philosopher();
        ph2.i = 2;
        ph3 = new Philosopher();
        ph3.i = 3;
        ph4 = new Philosopher();
        ph4.i = 4;
        ph5 = new Philosopher();
        ph5.i = 5;
    }

    private void lblp2_Click(object sender, EventArgs e)
    {

    }

    private void btnstart_Click(object sender, EventArgs e)
    {
        Thread.CurrentThread.Priority = ThreadPriority.Lowest;



        Thread t1 = new  Thread(ph1.main);
        Thread t2 = new  Thread(ph2.main);
        Thread t3 = new Thread(ph3.main);
        Thread t4 = new Thread(ph4.main);
        Thread t5 = new Thread(ph5.main);


        t1.Name = "t1";

        t2.Name = "t2";

        t3.Name = "t3";

        t4.Name = "t4";

        t5.Name = "t5";


      t1.Priority = ThreadPriority.Highest;
      t2.Priority = ThreadPriority.Highest;
      t3.Priority = ThreadPriority.Highest;
      t4.Priority = ThreadPriority.Highest;
      t5.Priority = ThreadPriority.Highest;
     // Thread.Sleep(100);
        t4.Start();
        Thread.Sleep(100);
        t1.Start();
        Thread.Sleep(100);
        t2.Start();
        Thread.Sleep(100);
        t3.Start();
        Thread.Sleep(100);
        t5.Start();
        Thread.Sleep(100);
    }
}

}

最佳答案

正如异常所暗示的,您正在从创建控件的线程之外的线程访问控件(具体来说,您的 ph1..5 线程都尝试访问 UI)。

要纠正这个问题,您需要在控件上使用 Invoke() 方法,以便在主 UI 线程上执行访问。

也许给Philosopher添加一个函数如下:

private void UpdateText(Label label, string text)
{
    // If the current thread is not the UI thread, InvokeRequired will be true
    if (label.InvokeRequired)
    {
        // If so, call Invoke, passing it a lambda expression which calls
        // UpdateText with the same label and text, but on the UI thread instead.
        label.Invoke((Action)(() => UpdateText(label, text)));
        return;
    }
    // If we're running on the UI thread, we'll get here, and can safely update 
    // the label's text.
    label.Text = text;
}

然后,只要你有类似的东西:

AZsys.Program.frm.lblp1.Text = "Eating...";

替换为:

UpdateText(AZsys.Program.frm.lblp1, "Eating...");

关于c# - C# :Cross-thread operation not valid: Control 'lblp4' accessed from a Cross-thread operation not valid 中的线程异常错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10565488/

相关文章:

C# 网络服务。需要可转换为 "string"

c# - 在用“,”和“。”定位小数时出错

c# - Visual Studio 2008 - 将构建时的文件移动到 bin/

java - 访问匿名内部类中封闭范围的成员变量

c++ - CreateFile,ReadDirectoryChanges 问题

java - 同时求和的最佳方法

c# - DataGridColumnHeader 中的 UserControl 不拉伸(stretch)

c# - WinForms 文本框中的换行符

c# - Monitor.Pulse 丢失信号?

java - 使用 BlockingQueue 时是否需要额外的同步?