2015-07-11 66 views
0

我正在學習使用線程並進行一些多線程演示。

我有一個名爲lblText的標籤和一個名爲pgbRun的選取框進度條。我製作了2個線程,一個讓標籤的文本在每個Thread.Sleep()調用後更改,其他讓標籤的文本更改時進度條顯示動畫。

我遇到的問題是文本更改線程似乎工作正常,但進度條線程有問題。 pgbRun剛剛開始動畫後文本更改完成。

請幫我看看我的代碼有什麼問題,並告訴我一些解決問題的方法。非常感謝!跑馬燈進度條有問題

private delegate void formDelegate(); 

private void btnRun_Click(object sender, EventArgs e) 
{ 
    Thread thread = new Thread(new ThreadStart(new formDelegate(textChange))); 
    thread.IsBackground = true; 
    thread.Start(); 
} 

public void textChange() 
{ 
    if (lblText.InvokeRequired) 
    { 
     lblText.BeginInvoke(new formDelegate(textChange)); 
    } 
    else 
    { 
     Thread thread = new Thread(new ThreadStart(new formDelegate(progess))); 
     thread.IsBackground = true; 
     thread.Start(); 

     //I try make single thread that config progress bar here but i have same trouble. 

     for (int i = 0; i < 10; i++) 
     { 
      lblText.Text = "Count: " + i; 
      lblText.Update(); 
      lblText.Refresh(); 
      Thread.Sleep(300); 
     } 
    } 
} 

public void progess() 
{ 
    if (pgbRun.InvokeRequired) 
    { 
     pgbRun.BeginInvoke(new formDelegate(progess)); 
    } 
    else 
    { 
     pgbRun.Style = ProgressBarStyle.Marquee; 
     pgbRun.MarqueeAnimationSpeed = 20; 
     pgbRun.Update(); 
     pgbRun.Refresh(); 
    } 
} 
+1

你的線程沒有做任何有用的事情,他們立即調用到UI線程。 textChange()代碼不能完成更多的事情,但會導致UI掛起3秒鐘。您可以看到標籤更改,因爲您調用Update()。 projss()中的BeginInvoke()調用在UI線程忙於睡眠3秒內停滯不前,因此您沒有看到進度條發生任何事情。你需要拋棄這些代碼。 –

+0

@HansPassant,我該如何解決它? – tungns304

回答

0

當我讀到this very useful article後,我看到#Hans是如此的真實。我的第一個代碼是垃圾,所以我編輯我的代碼如下。進度條的基本屬性在設計器中設置,在代碼中我只是更改可見選項。

delegate void textChangeDelegate(int x); 

private void btnRun_Click(object sender, EventArgs e) 
{ 
    Thread thread = new Thread(new ThreadStart(new MethodInvoker(threadJob))); 
    thread.IsBackground = true; 
    thread.Start(); 
} 

public void threadJob() 
{ 
    Invoke(new MethodInvoker(show)); 
    for (int i = 0; i < 10; i++) 
    { 
     Invoke(new textChangeDelegate(textChange),new object[]{i}); 
     Thread.Sleep(500); 
    } 
    Invoke(new MethodInvoker(hide)); 
} 

public void textChange(int x) 
{ 
    if (InvokeRequired) 
    { 
     BeginInvoke(new textChangeDelegate(textChange),new object[] {x}); 
     return; 
    } 
    x += 1; 
    lblText.Text = "Count: " + x; 
} 

public void show() 
{ 
    pgbRun.Visible = true; 
    lblText.Visible = true; 
} 

public void hide() 
{ 
    pgbRun.Visible = false; 
    lblText.Text = ""; 
    lblText.Visible = false; 
} 
0

您應該爲此使用Microsoft的Reactive Framework。這會讓它變得更容易。

下面的代碼:

private void btnRun_Click(object sender, EventArgs e) 
{ 
    Observable 
     .Interval(TimeSpan.FromMilliseconds(300.0)) 
     .Take(10) 
     .Select(n => String.Format("Count: {0}", n)) 
     .ObserveOn(this) 
     .Subscribe(t => lbl.Text = t); 
} 

就是這樣。

Just NuGet「Rx-WinForms」並將其添加到您的項目中。

目前還不清楚你試圖用進度條做什麼。你能否提供更詳細的信息?

+0

感謝您的回答。我試圖用兩個線程創建一個多線程演示。一個改變標籤的文本,其他「打開」進度條,而這些文本正在充電。我非常感謝你用這個漂亮的框架,但我需要解決線程和多線程問題。所以你的解決方案在未來應該對我有用。 – tungns304

+0

@ tungns304 - 這是多線程。它只是使用一個爲您管理線程的框架。 'ObserveOn(this)'之前的所有內容都發生在後臺線程上,然後再回到UI線程上。 – Enigmativity

+0

聽起來不錯。讓我看看那裏的文件。 – tungns304