2011-05-30 69 views
5

我與C#多線程問題。
表單內容是兩個按鈕和兩個標籤。

如果我按下第一個按鈕,會從1..to 60000循環,更新LABEL1。 (它的工作原理)

如果我按的第二個按鈕,會從1..to 6000循環更新標籤2,(我的形式滯後)。 (沒有迴應)
請幫忙!C#多線程

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

     } 
    } 
} 
+1

您是否嘗試用交替按鈕點擊。在Button2的第一個點擊,還看你是否通過投擲他們或印刷的地方 – AjayR 2011-05-30 11:53:00

+0

是得到任何例外..我做到了,但它是一個類似的問題 – Dezigo 2011-05-30 12:02:06

+0

趕上(例外五) { } FYI:這是非常糟糕的代碼。如果你得到一個異常,代碼將會掩蓋它,並且它會自動失敗。 – 2011-05-30 12:04:44

回答

1

嘗試使用lock語句

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

您768,16更改您的代碼

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

     } 
    } 
} 
+0

Thx它的作品! – Dezigo 2011-05-30 12:56:04

4

你最終落後,因爲調用(切換到另一個線程)是非常昂貴的操作,你在呼喚它過於頻繁

+0

我已經創建了一個新的線程。 (對於button2) – Dezigo 2011-05-30 11:58:30

+0

我不知道該怎麼辦.. – Dezigo 2011-05-30 11:59:09

+0

這不是問題。您只能在創建的線程中與gui元素進行交互。在你的情況下,它是主線。因此,當你啓動新線程並在那裏調用Invoke()時,動作切換到主線程並在那裏執行。 Invoke()的操作很昂貴,所以你會看到延遲 – Stecya 2011-05-30 12:01:49

2

試着在你的循環讓this.Refresh()Application.DoEvents()

+0

這種方法_might_可以工作,但通常您可能會嘗試使用這些構造來嘗試奇怪的結果。請參閱[本主題](http://stackoverflow.com/questions/5181777/c-application-doevents)以獲得有關該主題的更深入討論。 – 2011-05-30 12:23:22

+0

我得到了一個堆棧溢出嘗試這些。 – 2014-02-23 04:47:55

5

嘗試使用​​,並定期輪詢一個值,以受控的方式更新標籤。以您所做的方式更新UI將方式加載到系統上。
A System.Windows.Forms.Timer在GUI線程上運行。

只要確保看守共享資源在某種程度上,這個例子使用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 
    } 
} 

當然,你可以輕鬆地擴展這個例子,有兩個不同的計數器,計算出單獨的線程上,但仍然只使用一個定時更新整個UI,以適應你的榜樣。

0

把一些同步機制有

您可以使用

1。鎖定(本);

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

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


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