2009-06-11 50 views
4

這可能是一個愚蠢的問題,但我無法在stackoverflow上找到答案。從後臺線程結果更新WinForms UI

我有一個Winform應用程序中的按鈕單擊事件,該應用程序運行一個線程來整理結果以顯示在窗體中。

當線程計算出結果時,如何更新Forms UI?

private void btnRequestR2Approval_Click(object sender, EventArgs e) 
    { 
     if (User.IsLogged) 
     { 
      ValidationResults results = new ValidationResults(); 
      results.Show(); 

      Logger log = Logger.Instance(); 
      Logger.NewLogAddedHandler messageDelegate = new Logger.NewLogAddedHandler(results.NewLogMessage); 

      if (!log.IsEventHandlerRegistered()) 
      { 
       log.NewLogAdded += messageDelegate; 
      } 

      ThreadStart operation = new ThreadStart(ValidateAndSubmit); 
      Thread theThread = new Thread(operation); 
      theThread.Start(); 

     } 
     else 
     { 
      MessageBox.Show("Please login"); 
     } 

    } 

謝謝

+0

你在問ASP嗎。NET(網絡技術)還是Winforms(Windows本機技術)?這個問題看起來像你使用的WinForms,但標題和標籤表明否則。 – jrcs3 2009-06-11 20:04:25

+1

「完成跑步」是什麼意思?線程已經退出,或者線程已經計算出了您需要知道的內容? – 2009-06-11 21:04:27

+0

完成運行,意味着線程計算的東西,我需要刷新另一個線程中的東西 – Sergey 2009-06-11 21:07:37

回答

13

在WinForms中執行後臺任務的最簡單方法是使用BackgroundWorker

  • 將它放到表單上。
  • 接通事件。至少,使用DoWork。您可能還需要RunWorkerCompleted
  • DoWork事件中寫下您的後臺任務。
  • RunWorkerCompleted事件中編寫UI更改。
  • 撥打backgroundWorker1.RunWorkerAsync();即可啓動進程,可能來自某個按鈕處理程序。

使用BackgroundWorker可以避免所有惱人的線程處理和IsInvokeRequired內容。

下面是更詳細的how-to article

0

您可以 1.做一個theThread.Join()這將阻止調用線程。 2.將第一個線程傳遞給第二個線程,以便可以調用回主線程,這需要執行Invoke(),以便重繪表單。

雖然我很好奇。你使用Asp.Net(WebForms)還是WinForms?如果你想在網絡上做到這一點,那麼你將需要一個完全不同的方法。

2

嘗試使用的BeginInvoke有回調操作......這將推動你到另一個線程調用,當線程完成打電話給你所選擇的方法:

private void btnRequestR2Approval_Click(object sender, EventArgs e) 
{ 
    if (User.IsLogged) 
    { 
     ValidationResults results = new ValidationResults(); 
     results.Show(); 

     Logger log = Logger.Instance(); 
     Logger.NewLogAddedHandler messageDelegate = new Logger.NewLogAddedHandler(results.NewLogMessage); 

     if (!log.IsEventHandlerRegistered()) 
     { 

      log.NewLogAdded += messageDelegate; 
     } 

     ThreadStart operation = new ThreadStart(ValidateAndSubmit); 
     operation.BeginInvoke(MyCallBack, this); 
    } 
    else 
    { 
     MessageBox.Show("Please login"); 
    } 

} 

private static void MyCallBack(IAsyncResult ar) { 
    ((MyForm)ar.AsyncState).Refresh(); 
} 
2

非常不清楚的問題,我會承擔:

  1. 您正在運行Windows Winforms應用程序,而不是ASP.Net網頁。
  2. 你想觸發一個可能需要很長時間的背景計算,並且不希望你的UI在這種情況發生時被阻塞。
  3. 您希望您的UI在完成背景計算時獲得某種結果。
  4. 您希望當您的背景計算爲您的UI提供結果時退出。

如果是這樣,您應該使用異步委託,而不是線程。例如:

string SleepAndReturnParam(string param1) 
{ 
    System.Threading.Thread.Sleep(10000); 
    return param1; 
} 

// Declare a delegate matching our async method. 
public delegate string DelegateWithParamReturningString(string param1); 


private void button1_Click(object sender, EventArgs e) 
{ 
    var myDelegate = new DelegateWithParamReturningString(SleepAndReturnParam); 

    // Run delegate in thread pool. 
    myDelegate.BeginInvoke("param1", 
     OnCallBack, // Completion callback 
     this); // value to pass to callback as AsyncState 
} 


private void OnCallBack(IAsyncResult ar) 
{ 
    // first cast IAsyncResult to an AsyncResult object 
    var result = ar as System.Runtime.Remoting.Messaging.AsyncResult; 

    // grab the delegate 
    var myDelegate = result.AsyncDelegate as DelegateWithParamReturningString; 

    // Exit delegate and retrieve return value. 
    string returnValue = myDelegate.EndInvoke(ar); 

    // Declare an anonymous method to avoid having to define 
    // a method just to update a field. 
    MethodInvoker formFieldUpdater = delegate 
    { 
     formTextField.Text = returnValue; 
    }; 

    // Winforms controls must be modified on the thread 
    // they were created in. 
    if (formTextField.InvokeRequired) 
     Invoke(formFieldUpdater); 
    else 
     formFieldUpdater(); 
}