我知道这个问题可能没有意义,而且我正在努力想办法解释它,所以我会展示一段代码来帮助。我在visual studio express 2010上使用Winforms:
private void button1(object sender, EventArgs e)
{
txtOutput.Text += "Auto-collecting variables. This may take several minutes";
string v = foo();
txtOutput.Text += "\n" + v;
string b = bar();
txtOutput.Text += "\n" + b;
txtOutput.SelectionStart = txtOutput.Text.Length;
txtOutput.ScrollToCaret(); //scrolls to the bottom of textbox
}
所以基本上,当用户点击button1时,我希望“自动收集变量...”显示在文本框中,然后让foo()执行,显示它,然后执行bar(),然后显示。
当前正在发生的是foo()和bar()执行,然后在执行foo()和bar()之后一切都显示(需要几分钟的函数)。无论如何要解决这个问题,还是有解决方法?
编辑:C#的版本是4.0。如果我更新到4.5或5.0,没有.NET 4.5 / 5.0的计算机是否能够运行.exe?
答案 0 :(得分:6)
C#5.0让这件事变得微不足道。
使用Task.Run
在后台线程中执行长时间运行的任务,并使用await
作为UI线程中的延续执行方法的其余部分,而不会在异步期间阻止UI线程任务。
private async void button1(object sender, EventArgs e)
{
txtOutput.Text += "Auto-collecting variables. This may take several minutes";
string v = await Task.Run(() => foo());
txtOutput.Text += "\n" + v;
string b = await Task.Run(() => bar());
txtOutput.Text += "\n" + b;
txtOutput.SelectionStart = txtOutput.Text.Length;
txtOutput.ScrollToCaret(); //scrolls to the bottom of textbox
}
你可以在C#4.0中做同样的事情:(第一个解决方案将由编译器转换为类似的东西。)
private void button1(object sender, EventArgs e)
{
txtOutput.Text += "Auto-collecting variables. This may take several minutes";
Task.Factory.StartNew(() => foo())
.ContinueWith(t => txtOutput.Text += "\n" + t.Result
, TaskScheduler.FromCurrentSynchronizationContext())
.ContinueWith(t => bar())
.ContinueWith(t =>
{
txtOutput.Text += "\n" + t.Result;
txtOutput.SelectionStart = txtOutput.Text.Length;
txtOutput.ScrollToCaret(); //scrolls to the bottom of textbox
}
, TaskScheduler.FromCurrentSynchronizationContext());
}
答案 1 :(得分:3)
根据.NET的版本,您可以使用BackgroundWorker(Pre 4.0)或Tasks(Post 4.0 - 3.5 with a add-on)......仅举几例。
Backgroundworker Pseudocode:
var backgroundWorker = new BackgroundWorker()
method
{
//Update UI
backgroundWorker.RunWorkAsync()
}
asyncworkmethod
{
//do main logic
}
asynccompletemethod
{
//Update UI to say done
}
任务伪代码:
method
{
//Update UI
TaskFactory.StartNew(()=>DoWork).ContinueWith((previousTask)=>UpdateUIToSayDone)
}
而且,如果您使用4.5,那么您可以使用async/await
关键字,但这只是围绕任务的语法糖(主要是......)。虽然如果你采用那种方法,Servy已经有了一个很好的例子
答案 2 :(得分:2)
使用BackgroundWorker
类进行处理,而不会阻止UI更新。它具有可用于将进度信息传输到UI线程的事件。
答案 3 :(得分:0)
使用后台进程(阅读其他答案)是正确的方法,但如果您正在寻找一种非常快速的解决方法,则可以在更新TextBox后调用Application.DoEvents()
。在大多数情况下,此调用将导致您的表单更新以反映您所做的更改。
答案 4 :(得分:0)
txtOutput.Update()
应该做你想要的,但是你应该考虑使用后台线程来完成长时间运行的任务,而不会阻止UI线程。