2015-12-14 53 views
3

我正在使用ThreadPool來管理我的線程。與UI線程分開,我有一個線程執行數據檢索和一般工作操作,並且我有第三個線程更新UI以反映請求的操作的狀態。下面爲什麼我的多線程應用程序沒有做它應該做的事情?

見代碼:

// ui thread 
private void btnLoadClients_Click(object sender, EventArgs e) 
{ 
    // start thread 1 
    ThreadPool.QueueUserWorkItem(new Form1().LoadClientList); 
} 

// thread 1 
private void LoadClientList(object state) 
{ 
    ThreadBusy = true; 
    ThreadAction = "Loading Clients..."; 

    // start thread 2 
    ThreadPool.QueueUserWorkItem(new Form1().ShowProgress); 

    // get data 
    ClientController c = new ClientController(); 
    List<Client> clients = c.GetClient(); 

    foreach (Client item in clients) 
    { 
     cmbClientList.Items.Add(item.Name); 
    } 
    cmbClientList.Items.Insert(0, "Please select a client"); 

    ThreadBusy = false; 
} 

// thread 2 
private void ShowProgress(object state) 
{ 
    while (ThreadBusy) 
    { 
     foreach (string action in lstAction.Items) 
     { 
      // write the action that's being taken to the listbox 
      if (String.Compare(action, ThreadAction) != 0) 
       lstAction.Items.Add(ThreadAction); 
     }     
    } 
} 

問題是,雖然當我設置一個斷點它ShowProgress正在熱播,執行不進入它真的。 while (ThreadBusy)線路不會被擊中。

我在這裏有什麼問題嗎?

+0

使用'delegates'從其他線程UI線程更新的東西。 – Neijwiert

+0

只需使用BackgroundWorker。它專門設計用來做到這一點。或者使用'Task'和'await'。 – Servy

+1

@Neijwiert他*使用委託,他只是沒有使用正確的操作來編組到UI線程,他也沒有做正確的事情,我這個方法做他想做的事情,即使他們在UI線程中運行。 – Servy

回答

5
ThreadPool.QueueUserWorkItem(new Form1().LoadClientList); 

ThreadPool.QueueUserWorkItem(new Form1().ShowProgress); 

您正在創建新的Form1情況下,每次啓動一個後臺線程的時候,每一次你在這些方法中採取的行動將發生在這些新的,「無界」的實例,而不是在一個與用戶交互。

如果您想在WinForms中執行後臺工作,您可以利用BackgroundWorker類。

一個很簡單的例子:

public static class Program 
{ 
    public static void Main() 
    { 
     var backgroundWorker = new BackgroundWorker(); 

     backgroundWorker.WorkerReportsProgress = true 

     backgroundWorker.Disposed += BackgroundWorker_Disposed; 
     backgroundWorker.DoWork += BackgroundWorker_DoWork; 
     backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged; 
     backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted; 

     backgroundWorker.RunWorkerAsync(); 
    } 

    private static void BackgroundWorker_Disposed(object sender, EventArgs e) 
    { 
     // Cleanup after yourself. 
    } 

    private static void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // Do your things in background. 
    } 

    private static void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     // Notify progress. 
    } 

    private static void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     // The background task is complete ("successfully" is NOT implied). 
    } 
} 
+1

雖然在技術上是正確的,但如果它包含修復或一些關於如何解決問題的一般性建議,這將是一個更好的答案。 –

+0

@BradleyUffner我完全同意你的看法,但是我很久沒有使用過WinForms,我無法通過記憶提出最佳的行動方案。我正在尋找它,但如果任何人都可以提供和示例在此期間,他是受歡迎的。 – Albireo

+0

我會先發送一個對現有表單的引用,而不是發送一個新的實例。看看代碼,看起來現在會導致跨線程問題,因爲線程池線程將觸及UI。解決這個問題的方法是正確使用'InvokeRequired'和'BeginInvoke'。 'ShowProgress'也許應該以某種方式受到限制,這樣就不會通過持續更新來扼殺UI線程。 –

0

ThreadBusy屬性,您設置爲true屬於不同的Form1的對象。因爲運行ShowProgress的線程在Form1的新實例上執行,並且其ThreadBusy屬性始終爲false。這就是爲什麼它沒有進入while循環。

你可以試試這個

ThreadPool.QueueUserWorkItem(this.ShowProgress); 

代替

ThreadPool.QueueUserWorkItem(new Form1().ShowProgress); 
相關問題