我如何使用后台工作程序让我的GUI响应?

时间:2015-07-22 18:53:03

标签: c#

我制作了一个只有一个按钮的简短程序。按下按钮时,执行functionA,也使用functionB和functionC。函数内部A是一个执行functionB和functionC X次数的循环。在每个循环结束时,进度条增加1.在函数A的开头,循环之前,有一个web服务从网站提取数据,并将其传递到B和C进行处理(数据文件操作)并保存到磁盘)。

我的问题是一切正常,但是当functionA仍在运行时,GUI被卡住了,所以我无法关闭/最小化/拖动窗口,我必须等到A完成。我研究过,他们说我应该使用BackgroundWorker,但作为一名新程序员,我不知道如何使用它。有人可以给我一个简单的方法来使用它吗?

进度条加载正常,但它只是在函数运行时,整个窗口被冻结,我想要它所以我可以在程序运行时移动窗口等,而不是等待直到功能完成。

谢谢!

2 个答案:

答案 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是推荐的   新开发的异步设计模式。