2012-05-12 56 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..."; 

將其替換可以看到是從線程

贊助的用戶界面