简体   繁体   English

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

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

I made a short program which has just a button. 我制作了一个只有一个按钮的简短程序。 When the button is pressed, functionA is executed, which also uses functionB and functionC. 当按下按钮时,将执行功能A,该功能也将使用功能B和功能C。 Inside functionA is a loop which executes functionB and functionC X amount of times. 在functionA内部是一个循环,循环执行functionB和functionC X次。 At the end of each loop, the progressbar gets incremented by 1. At the beginning of functionA, before the loop, there's a webservice which pulls data from a website, and passes that onto B and C for processing (data file manipulation and saving to disk). 在每个循环的末尾,进度条将增加1。在功能A的开始处,在循环前,有一个Web服务将从网站上提取数据,并将其传递给B和C进行处理(将数据文件进行处理并保存到磁盘)。

My problem is that everything works fine, but while functionA is still running, the GUI is stuck, so I can't close/minimize/drag the window around, I have to wait until A is done. 我的问题是,一切正常,但是当functionA仍在运行时,GUI卡住了,因此我无法关闭/最小化/拖动周围的窗口,我必须等到A完成之后。 I researched and they say I should use BackgroundWorker, but as being a new programmer, I've no idea on how to use it. 我进行了研究,他们说我应该使用BackgroundWorker,但是作为一名新程序员,我不知道如何使用它。 Can someone give me a simple way to use it? 有人可以给我一种简单的使用方法吗?

The progressbar loads fine, but it's just that while the function is running, the whole window is frozen, and I want it so I can move the window around, etc while the program is running, instead of waiting until the function is complete. 进度条可以很好地加载,但是仅仅是在函数运行时,整个窗口都被冻结了,所以我想要它,以便我可以在程序运行时四处移动窗口,而不必等到函数完成为止。

Thank you! 谢谢!

Call your function asynchronously like the following and it will not freeze the UI. 像下面这样异步调用函数,它不会冻结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..
}

To run your task, simply call BeginProcessingAsync(d); 要运行任务,只需调用BeginProcessingAsync(d); . Also, please note: If you're using newer versions of .NET, you might have to use await Task.Factory.StartNew(() => functionA(d)); 另外,请注意:如果使用的是.NET的较新版本,则可能必须使用await Task.Factory.StartNew(() => functionA(d)); instead of the above 代替上面

Overall, you'll want to make sure your GUI doesn't get updated from another thread. 总体而言,您需要确保您的GUI不会从其他线程更新。 Instead, the messages should go to a threadsafe location. 而是,消息应转到线程安全的位置。 For instance , you could have the thread building into something like a database and have the GUI using a timer to look for updated data flags. 例如 ,您可以将线程构建到类似数据库的对象中,并让GUI使用计时器来查找更新的数据标志。

There is a question with a lot more detail using delegates here . 这里有一个使用委托的问题,其中有更多细节

Marc's answer was the simplest and best, in my opinion: 在我看来, 马克的答案是最简单,最好的:

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

From Dotnet Perls : Dotnet Perls

A Background Worker makes threads easy to implement in Windows Forms. 后台工作程序使线程易于在Windows窗体中实现。 Intensive tasks need to be done on another thread so the UI does not freeze. 需要在另一个线程上完成繁重的任务,因此UI不会冻结。 It is necessary to post messages and update the user interface when the task is done. 完成任务后,有必要发布消息并更新用户界面。

Also, from MSDN , look at Task-based Asynchronous Pattern (TAP) if you're using C# 5. 另外,如果您使用的是C#5,请从MSDN中查看基于任务的异步模式 (TAP)。

The Task-based Asynchronous Pattern (TAP) is based on the System.Threading.Tasks.Task and System.Threading.Tasks.Task types in the System.Threading.Tasks namespace, which are used to represent arbitrary asynchronous operations. 基于任务的异步模式(TAP)基于System.Threading.Tasks命名空间中的System.Threading.Tasks.Task和System.Threading.Tasks.Task类型,用于表示任意异步操作。 TAP is the recommended asynchronous design pattern for new development. TAP是新开发的推荐异步设计模式。

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

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