2009-06-11 74 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(); 
}