我制作了一个只有一个按钮的简短程序。按下按钮时,执行functionA,也使用functionB和functionC。函数内部A是一个执行functionB和functionC X次数的循环。在每个循环结束时,进度条增加1.在函数A的开头,循环之前,有一个web服务从网站提取数据,并将其传递到B和C进行处理(数据文件操作)并保存到磁盘)。
我的问题是一切正常,但是当functionA仍在运行时,GUI被卡住了,所以我无法关闭/最小化/拖动窗口,我必须等到A完成。我研究过,他们说我应该使用BackgroundWorker,但作为一名新程序员,我不知道如何使用它。有人可以给我一个简单的方法来使用它吗?
进度条加载正常,但它只是在函数运行时,整个窗口被冻结,我想要它所以我可以在程序运行时移动窗口等,而不是等待直到功能完成。
谢谢!
答案 0 :(得分:1)
如下所示异步调用您的函数,它不会冻结UI。
private async void BeginProcessingAsync(Data d)
{
//Execute the long running task asynchronously
await Task.Run(() => functionA(d));
//Anything after the await line will be executed only after the task is finished.
anotherFunction(d); // if you have one..
}
要运行您的任务,只需致电BeginProcessingAsync(d);
即可。此外,请注意:如果您使用的是较新版本的.NET,则可能必须使用await Task.Factory.StartNew(() => functionA(d));
而不是上述
答案 1 :(得分:0)
总的来说,您要确保您的GUI不会从其他线程获得更新。相反,消息应该转到线程安全位置。 例如,您可以将线程构建为类似数据库的东西,并使用定时器来查找更新的数据标记。
有很多问题more detail using delegates here。
在我看来,Marc's回答是最简单和最好的:
///...blah blah updating files
string newText = "abc"; // running on worker thread
this.Invoke((MethodInvoker)delegate {
someLabel.Text = newText; // runs on UI thread
});
///...blah blah more updating files
来自 Dotnet Perls :
Background Worker使线程易于在Windows中实现 形式。需要在另一个线程上完成密集型任务,以便进行UI 不会冻结。有必要发布消息并更新用户 任务完成后的界面。
此外,从 MSDN ,如果您正在使用C#5,请查看Task-based Asynchronous Pattern(TAP)。
基于任务的异步模式(TAP)基于 System.Threading.Tasks.Task和System.Threading.Tasks.Task System.Threading.Tasks命名空间中的类型,用于 表示任意异步操作。 TAP是推荐的 新开发的异步设计模式。