2012-05-12 54 views
0

首先,对于我的弱英语语言感到抱歉,我是初学程序员。在项目中,我使用线程级的,但是当它完成我看到这个异常:C#中的线程异常错误:跨线程操作无效:通过跨线程操作访问的控制'lblp4'无效

跨线程操作无效:控制“lblp4”从比它创建的线程以外的 线程访问。

在我的项目,我在Form1类调​​用5个功能SynchronizePhilosopher类:

Philosopher类:

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

}

回答

4

作为例外建议,你从比创建该控件的一个(具体而言,您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; 
} 

然后,只要你有这样的:

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

主要的问题我:

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

将其替换可以看到是从线程

赞助的用户界面