我怎么能等待一个BackgroundWorker的完成?我怎么能、BackgroundWorker

2023-09-06 14:26:38 作者:赠风给你

我想使用的BackgroundWorker 来从GUI执行数据库事务。

I would like to use the BackgroundWorker to perform a database transaction from a GUI.

我怎么能指挥的BackgroundWorker 执行工作,然后等待工作完成,同时保持GUI响应?

How can I command the BackgroundWorker to perform the work and then WAIT for the worker to complete while keeping the GUI responsive?

我一定要使用的DoEvents 为了这个目的,或者是有另一种方式?

Do I have to use DoEvents for this purpose, or is there another way?

推荐答案

问:我怎么可以命令的BackgroundWorker 执行工作,然后等待工作完成同时保持GUI作出响应?真的是问我如何使用的BackgroundWorker ?。这就是的BackgroundWorker 的确实的。

Asking "How can I command the BackgroundWorker to perform the work and then WAIT for the worker to complete while keeping the GUI responsive?" is really asking "How do I use the BackgroundWorker?". That's what BackgroundWorker does.

当你写一个后台任务,你基本上分手的方法分为四个部分:

When you write a background task, you're basically breaking up a method into four pieces:

准备工作运行的任务。 在任务本身。 报告进展到UI任务运行时。 在清理东西时,任务就完成了。

所以,你将需要写四种方法。首先是创建一个的BackgroundWorker ,添加事件处理程序的的DoWork ProgressChanged方法 RunWorkerCompleted 事件,使用户界面到任何状态,它需要在任务运行时,并呼吁的RunWorkerAsync 来启动任务。

So you're going to need to write four methods. The first is a method that creates a BackgroundWorker, adds event handlers to its DoWork, ProgressChanged, and RunWorkerCompleted events, puts the UI into whatever state it needs to be in while the task is running, and calls RunWorkerAsync to start the task.

另外三个是这三个事件处理程序。 的DoWork DoWorkEventHandler ,做的工作,并调用 ReportProgress 每当需要报告其到UI进展。 ProgressChanged ProgressChangedEventHandler 实际更新UI时 ReportProgress 被调用。而 RunWorkerCompleted RunWorkerCompletedEventHandler ,告诉作业完成用户界面。

The other three are those three event handlers. DoWork is a DoWorkEventHandler that does the work, and that calls ReportProgress whenever it needs to report its progress to the UI. ProgressChanged is a ProgressChangedEventHandler that actually updates the UI when ReportProgress gets called. And RunWorkerCompleted is a RunWorkerCompletedEventHandler that tells the UI that the job is done.

这是所有有给它。

嗯,不太的所有的。首先,你必须确保你检查和处理的错误属性在完成处理。如果你不这样做,你就没有办法知道你做的,工作方法抛出一个异常,因为它没有发生在UI线程,因此不会引发异常,你可以看到。 (它会显示在输出窗口,如果你正在寻找它。)

Well, not quite all. First, you have to make sure that you check and handle the Error property in your completion handler. If you don't do this, you will have no way of knowing that your do-work method threw an exception, since it's not happening in the UI thread and thus doesn't throw an exception that you can see. (It'll show up in the Output window, if you're looking for it.)

其次,你必须确保该 DoWorkEventHandler 不在UI碰任何东西。这可以,如果你使用MVVM模式是棘手的,你有没有计划在今年意外,因为通过数据绑定,你可能有东西在你的模型更新用户界面绑定到的意见的神奇,这意味着,操作模式在做,工作方法的是的操纵界面。假设你正在实施 INotifyPropertyChanged的,一个很好的方式,以避免麻烦,这里是要建立一个机制,使你的意见不养的PropertyChanged 事件,而后台任务运行。

Second, you have to make sure that the DoWorkEventHandler doesn't touch anything in the UI. This can be tricky if you're using the MVVM pattern and you haven't planned for this contingency, because through the magic of data binding you probably have things in your model that update the views that the UI is bound to, which means that manipulating the model in your do-work method is manipulating the UI. Assuming that you're implementing INotifyPropertyChanged, a good way to avoid trouble here is to build a mechanism whereby your views don't raise PropertyChanged events while a background task is running.

您还需要弄清楚的UI件应在任务运行时被禁用。这取决于你的用户界面。答案可能是所有的一切,它可能不会。其中之一是使得使用模式窗体为您的进度指示器有吸引力的事情之一是,它释放您不必想出解决办法,因为你的整个UI被禁用,而模态窗体处于打开状态。如果你禁用控制或关闭属性更改通知中的启动方法,你需要把事情再重新在完成方式。

You also need to figure out what pieces of the UI should be disabled while the task is running. This depends on your UI. The answer might be "all of it," and it might not. One of the things that makes using a modal form for your progress indicator attractive is that it frees you up from having to figure this out, since your entire UI is disabled while the modal form is open. If you're disabling controls or turning off property-change notifications in the launch method, you'll need to turn things back on again in the completion method.

请记住:任何更新,UI的有源器件对您的数据模型是跨线程的数据访问错误的潜在来源。如果你的UI和后台线程不断更新同一个对象,不好的事情发生 - 他们是特别不好,如果你还没有处理的错误属性在你完成处理,并跨线程异常杀死你不知道它的后台任务。如果这听起来像我居住的这个,是因为我已经失去了很多我生命中的时间做这个特殊的事情是错误的。

And remember: any updates that the active parts of your UI make to your data model are a potential source of cross-thread data access errors. If your UI and the background thread ever update the same object, bad things happen - they're particularly bad if you haven't handled the Error property in your completion handler, and the cross-thread exception kills the background task without your knowing it. If it sounds like I'm dwelling on this, it's because I've lost a lot of hours of my life to doing this particular thing wrong.