繁体   English   中英

我将如何使用Background Worker来使GUI响应?

[英]How would I use Background Worker to get my GUI to respond?

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

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

进度条可以很好地加载,但是仅仅是在函数运行时,整个窗口都被冻结了,所以我想要它,以便我可以在程序运行时四处移动窗口,而不必等到函数完成为止。

谢谢!

像下面这样异步调用函数,它不会冻结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)); 代替上面

总体而言,您需要确保您的GUI不会从其他线程更新。 而是,消息应转到线程安全的位置。 例如 ,您可以将线程构建到类似数据库的对象中,并让GUI使用计时器来查找更新的数据标志。

这里有一个使用委托的问题,其中有更多细节

在我看来, 马克的答案是最简单,最好的:

///...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

后台工作程序使线程易于在Windows窗体中实现。 需要在另一个线程上完成繁重的任务,因此UI不会冻结。 完成任务后,有必要发布消息并更新用户界面。

另外,如果您使用的是C#5,请从MSDN中查看基于任务的异步模式 (TAP)。

基于任务的异步模式(TAP)基于System.Threading.Tasks命名空间中的System.Threading.Tasks.Task和System.Threading.Tasks.Task类型,用于表示任意异步操作。 TAP是新开发的推荐异步设计模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM