[英]How to program asynchronous Windows Forms Applications?
I'm writting a Windows Forms application in C# that performs a lot of long-running procedures. 我正在用C#编写一个Windows Forms应用程序,该应用程序执行许多长时间运行的过程。 I need to program the application so that the GUI doesn't lock.
我需要对应用程序进行编程,以使GUI不会锁定。 What is the best way to program it?
编程的最佳方法是什么?
I know how to use the following: 我知道如何使用以下内容:
BeginInvoke
/ EndInvoke
BeginInvoke
/ EndInvoke
Application.DoEvents()
repeatedly (probably not a good idea) Application.DoEvents()
(可能不是一个好主意) BackgroundWorker
But how to manage GUI state with call backs, etc... is not trivial. 但是,如何通过回调等方式管理GUI状态并非易事。 Are there solutions for this (in the form of patterns or libraries)?
是否有解决方案(以模式或库的形式)?
Using BackgroundWorker
is the simplest way to do what you're trying to do. 使用
BackgroundWorker
是执行您要执行的操作的最简单方法。 BackgroundWorker
simplifies the logic of dealing with threads, leaving you with very little code you have to write. BackgroundWorker
简化了处理线程的逻辑,从而使您只需要编写很少的代码。 You just have to handle three events ( DoWork
, ProgressChanged
, and RunWorkerCompleted
) and follow a few principles: 您只需要处理三个事件(
DoWork
, ProgressChanged
和RunWorkerCompleted
),并遵循一些原则:
ReportProgress
instead and handle the ProgressChanged
event in the UI logic. ReportProgress
并在UI逻辑中处理ProgressChanged
事件。 Error
property of the RunWorkerCompletedEventArgs
when the method is done and handle (or throw) the exception. RunWorkerCompletedEventArgs
的Error
属性非常重要。 If you don't do this, you won't know that your method failed. CancellationPending
property to see if cancellation has been requested. CancellationPending
属性以查看是否已请求取消。 If it has, once it's done handling the cancellation, set the Cancel
property on the DoWorkEventArgs
object. DoWorkEventArgs
对象上设置Cancel
属性。 Be aware that it's possible for CancellationPending
to be true and Cancel
to be false; CancellationPending
可能为true, Cancel
可能为false。 this happens, for instance, when the user requests cancellation and the method finishes before it has a chance to check CancellationPending
. CancellationPending
之前完成时,就会发生这种情况。 Cancel
in your RunWorkerCompleted
event handler, so that your UI can provide the proper response to what happened while the worker was running. RunWorkerCompleted
事件处理程序中选中“ Cancel
,以便您的UI可以对工作程序运行时发生的情况提供正确的响应。 The examples in the documentation all show the DoWork
event handler calling a method of the form. 文档中的所有示例均显示了调用表单方法的
DoWork
事件处理程序。 This is almost certainly not what you want to do. 几乎可以肯定这不是您想要做的。 Separating business logic from UI is a good idea in general;
通常,将业务逻辑与UI分开是一个好主意。 in background tasks it's essential.
在后台任务中,这是必不可少的。 If your long-running method is a member of a class that doesn't know that the UI even exists, there's no danger that you'll inadvertently have it call a method that updates a status bar or something.
如果您长时间运行的方法是不知道UI甚至不存在的类的成员,那么就不会有您无意间让它调用更新状态栏或其他内容的方法的危险。
The Model-View-Controller pattern separates the state of your UI from the visual aspects of the UI. Model-View-Controller模式将UI的状态与UI的视觉方面分开。 As long as your MVC implementation is thread aware, it should solve the state management issue for you.
只要您的MVC实现是线程感知的,它就可以为您解决状态管理问题。
This is how I handle multi-threaded UI implementations. 这就是我处理多线程UI实现的方式。
EDIT: Here's a good post on selecting an MVC implementation for WinForms projects. 编辑:这是为WinForms项目选择MVC实现的好帖子 。
It is relatively simple to use the ThreadPool to fire off long running processes from the UI. 使用ThreadPool从UI触发长时间运行的进程相对简单。 If you want feedback you can use some event handlers to fire on certain events from the long running process, then register for them and update the UI as needed.
如果您需要反馈,则可以使用一些事件处理程序在长时间运行的过程中触发某些事件,然后为它们注册并根据需要更新UI。
MVC is good, but you still need to make sure your process is firing off on a thread other than the UI thread. MVC很好,但是您仍然需要确保您的进程在UI线程以外的其他线程上触发。
All your options are syntactic sugar of doing same thing (Asynchronous execution). 您所有的选择都是做同一件事(异步执行)的语法糖。 May be with different levels of controls.
可能具有不同级别的控件。 I would go with BackgroundWorker, because your GUI (handled by the main thread) will always be responsive.
我将使用BackgroundWorker,因为您的GUI(由主线程处理)将始终响应。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.