这可能是一个愚蠢的问题,但我找不到stackoverflow的答案。
我在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 :(得分:13)
在WinForms中执行后台任务的最简单方法是使用BackgroundWorker。
DoWork
。您可能还需要RunWorkerCompleted
。DoWork
事件中编写后台任务。 RunWorkerCompleted
事件中写下任何UI更改。backgroundWorker1.RunWorkerAsync();
启动该过程,可能来自某个按钮处理程序。使用BackgroundWorker可以避免所有恼人的线程处理和IsInvokeRequired。
以下是更详细的how-to article。
答案 1 :(得分: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 :(得分:2)
非常不清楚的问题,我会假设:
如果确实如此,那么您应该使用异步委托,而不是线程。例如:
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();
}
答案 3 :(得分:0)
你也可以
1.做一个会阻塞调用线程的theThread.Join()
。
2.将第一个线程传递给第二个线程,以便它可以回调到主线程,这需要执行Invoke()
,以便重绘表单。
我很好奇。您使用的是Asp.Net(WebForms)还是WinForms?如果您尝试在网络上执行此操作,那么您将需要一种完全不同的方法。