https://msdn.microsoft.com/zh-cn/library/wewwczdw(v=vs.110).aspx
Applications that perform many tasks simultaneously, yet remain responsive to user interaction, often require a design that uses multiple threads.
同时执行多项任务,并且仍要相应用户交互的应用,通常需要一个使用多线程的设计。
The System.Threading namespace provides all the tools necessary to create high-performance multithreaded applications,
System.Threading命名空间提供了所有必要的工具来创建高效的多线程应用
but using these tools effectively requires significant experience with multithreaded software engineering.
但是有效的使用这些工具需要有丰富的使用多线程软件工程的经验
For relatively simple multithreaded applications, the BackgroundWorker component provides a straightforward solution.
相较而言,简单的多线程应用,BackgroundWorker组件提供一个简单的解决方案
For more sophisticated asynchronous applications, consider implementing a class that adheres to the Event-based Asynchronous Pattern.
对于更复杂的亦不应用,可以考虑实现一个支持基于事件的异步模式的类
The Event-based Asynchronous Pattern makes available the advantages of multithreaded applications while hiding many of the complex issues inherent in multithreaded design. Using a class that supports this pattern can allow you to:
基于事件的一步模式,利用了多线程应用的优点,同时隐藏了多线程设计中固有的复杂问题,使用支持此模式的类,可以确保你:
1.Perform time-consuming tasks, such as downloads and database operations, "in the background," without interrupting your application.
在后台执行耗时的任务,比如下载或者数据库操作,但是不会中断你的应用
2.Execute multiple operations simultaneously, receiving notifications when each completes.
同时执行多个操作,当每一个操作都完成的时候,接收通知
3.Wait for resources to become available without stopping ("hanging") your application.
等待资源可用,而且不会停止你的应用
4.Communicate with pending asynchronous operations using the familiar events-and-delegates model.
使用熟悉的事件委托模式,来和挂起的异步操作通讯
A class that supports the Event-based Asynchronous Pattern will have one or more methods named MethodNameAsync.
一个支持基于事件的异步模式的类,会有一个或多个方法,按照方法名+后缀Async的规则来命名。
These methods may mirror synchronous versions, which perform the same operation on the current thread.
这些方法可能都有对应的同步版本,在当前线程上有同样的操作。
The class may also have a MethodNameCompleted event and it may have a MethodNameAsyncCancel (or simply CancelAsync) method.
这个类也许还有方法名+Completed后缀的事件,也许有方法名+AsyncCancel后缀的方法(或者直接就是CancelAsync)。
PictureBox is a typical component that supports the Event-based Asynchronous Pattern.
PictureBox就是一个支持基于事件的异步模式的典型组件。
You can download an image synchronously by calling its Load method, but if the image is large, or if the network connection is slow, your application will stop ("hang") until the download operation is completed and the call to Load returns.
你可以调用Load方法来同步下载一张图片,但是如果图片太大的话或者网速太慢的话,你的应用将会停止响应(或挂起),直到下载操作完成并且调用Load方法返回。
If you want your application to keep running while the image is loading, you can call the LoadAsync method and handle the LoadCompleted event, just as you would handle any other event.
如果你想要你的应用边运行边下载图片,你可以调用LoadAsync方法并处理LoadCompleted事件
When you call the LoadAsync method, your application will continue to run while the download proceeds on a separate thread ("in the background").
当你调用LoadAsync方法的时候,你的应用可以继续运行,而下载将会在一个独立的线程上开始(后台)
Your event handler will be called when the image-loading operation is complete, and your event handler can examine the AsyncCompletedEventArgs parameter to determine if the download completed successfully.
你的事件处理器将会在图片下载操作完成的时候被调用,事件处理器可以通过检查AsyncCompletedEventArgs参数来判断下载是否成功完成。
The Event-based Asynchronous Pattern requires that an asynchronous operation can be canceled, and the PictureBox control supports this requirement with its CancelAsync method.
基于事件的异步模式需要保证一个异步操作可以被取消,PictureBox控件通过它的CancelAsync方法来支持这个要求。
Calling CancelAsync submits a request to stop the pending download, and when the task is canceled, the LoadCompleted event is raised.
调用CancelAsync提交一个请求来停止下载操作,当任务被取消的时候,将会触发LoadCompleted事件
注意:
It is possible that the download will finish just as the CancelAsync request is made, so Cancelled may not reflect the request to cancel.
有一种可能,下载会在你刚调用了CancelAsync的时候完成,导致事件参数中的Cancelled可能无法反映取消的
This is called a race condition and is a common issue in multithreaded programming.
这种现象被称为争用条件,这是多线程编程中很常见的一个问题
Characteristics of the Event-based AsyncChronous Pattern基于事件的一步模式的特征
The Event-based Asynchronous Pattern may take several forms, depending on the complexity of the operations supported by a particular class.
基于事件的异步模式可能有多种表现形式,这取决于特定类所支持的操作的复杂程序
The simplest classes may have a single MethodNameAsync method and a corresponding MethodNameCompleted event.
最简单类只有一个MethodNameAsync方法以及一个对应的MethodNameCompleted事件
More complex classes may have several MethodNameAsync methods, each with a corresponding MethodNameCompleted event, as well as synchronous versions of these methods.
更复杂的类会有多个MethodNameAsync方法,并且每个方法都有对应的MethodNameCompleted事件,除此之外,这些异步方法还有对应的同步方法。
Classes can optionally support cancellation, progress reporting, and incremental results for each asynchronous method.
An asynchronous method may also support multiple pending calls (multiple concurrent invocations), allowing your code to call it any number of times before it completes other pending operations.
异步方法可能支持多个挂起调用(多个并发的调用),允许你在它完成其他挂起操作之前调用此方法任意多次。
Correctly handling this situation may require your application to track the completion of each operation.
为了处理这种情况,这就要求你的应用可以追踪每一个操作的完成进度
- 1.Examples of the Event-based AsyncChronous Pattern基于事件的异步模式的例子
The SoundPlayer and PictureBox components represent simple implementations of the Event-based Asynchronous Pattern.
SoundPlayer组件以及PictureBox组件,代表了基于事件的异步模式的简单实现。
The WebClient and BackgroundWorker components represent more complex implementations of the Event-based Asynchronous Pattern.
WebClient组件以及BackgroundWorker组件,代表了基于事件的一步模式的更复杂的实现
Below is an example class declaration that conforms to the pattern:
下面是一个符合此模式的范例类的声明:
public class AsyncExample { // Synchronous methods. public int Method1(string param); public void Method2(double param); // Asynchronous methods. public void Method1Async(string param); public void Method1Async(string param, object userState); public event Method1CompletedEventHandler Method1Completed; public void Method2Async(double param); public void Method2Async(double param, object userState); public event Method2CompletedEventHandler Method2Completed; public void CancelAsync(object userState); public bool IsBusy { get; } // Class implementation not shown. }
The fictitious AsyncExample class has two methods, both of which support synchronous and asynchronous invocations.
虚构的AsyncExample类有2个方法,它们都支持同步和异步调用
The synchronous overloads behave like any method call and execute the operation on the calling thread;
同步重载就像其他任何方法调用一样在调用的线程上来执行操作
if the operation is time-consuming, there may be a noticeable delay before the call returns.
如果这个操作是耗时的,那么在方法返回之前会有一个很明显的延时
The asynchronous overloads will start the operation on another thread and then return immediately, allowing the calling thread to continue while the operation executes "in the background."
异步重载将会在另外一个线程上执行操作并立即返回,当操作在后台执行的时候,允许调用线程继续执行。
- 2.AsyncChronous Method Overloads异步方法的重载
There are potentially two overloads for the asynchronous operations: single-invocation and multiple-invocation.
对异步操作而言,有2个潜在的重载:单次调用以及多次调用
You can distinguish these two forms by their method signatures: the multiple-invocation form has an extra parameter called userState.
你可以通过它们的方法签名来区分这2种形式,多次调用的形式有一个叫做userState的额外参数
This form makes it possible for your code to call Method1Async(string param, object userState) multiple times without waiting for any pending asynchronous operations to finish.
多次调用的形式确保了如下操作变得可能:让你的代码可以多次调用Method1Async(string param, object userState)方法多次而无需等待挂起的异步操作结束
If, on the other hand, you try to call Method1Async(string param) before a previous invocation has completed, the method raises an InvalidOperationException.
另一方面,如果你在之前的调用还没有结束前,尝试再次调用Method1Async(string param)这个同步方法的时候,这个同步方法将会触发一个无效操作的异常
The userState parameter for the multiple-invocation overloads allows you to distinguish among asynchronous operations.
多次调用的重载参数userState允许你区分不同的异步操作
You provide a unique value (for example, a GUID or hash code) for each call to Method1Async(string param, object userState),
你可以在每一次调用Method1Async(string param, object userState)方法时,使用一个独一无二的值传递给此方法(比如GUID或哈希码)
and when each operation is completed, your event handler can determine which instance of the operation raised the completion event.
当每次操作完成的时候,你的事件处理器可以依据这个独一无二的值来判断哪一个操作实例触发了完成事件
- 3.Tracking Pending Operations追踪挂起的操作
If you use the multiple-invocation overloads, your code will need to keep track of the userState objects (task IDs) for pending tasks.
如果你使用多次调用的重载,你的代码需要通过userState对象(任务编号)来追踪挂起的任务
For each call to Method1Async(string param, object userState), you will typically generate a new, unique userState object and add it to a collection.
每一次调用Method1Async(string param, object userState)方法时,你通常需要生成一个新的,独一无二的userState对象,并将它加入到一个结合中。
When the task corresponding to this userState object raises the completion event, your completion method implementation will examine AsyncCompletedEventArgs.UserState and remove it from your collection.
当和这个userState对象符合的任务触发了完成事件时,你的完成方法实现,需要检查AsyncCompletedEventArgs.UserState,并且将它从集合中移除。
Used this way, the userState parameter takes the role of a task ID.
通过这种方法,userState参数扮演了任务编号的角色
注意:
You must be careful to provide a unique value for userState in your calls to multiple-invocation overloads.
在你调用多次调用重载的时候,你必须足够小心来为userState提供一个独一无二的值。
Non-unique task IDs will cause the asynchronous class throw an ArgumentException.
如果任务编号不是独一无二的话,将会导致异步类抛出一个参数错误的异常
- 4.Canceling Pending Operations取消挂起的操作
It is important to be able to cancel asynchronous operations at any time before their completion.
在异步操作完成之前,要确保可以随时取消异步操作,这很重要。
Classes that implement the Event-based Asynchronous Pattern will have a CancelAsync method (if there is only one asynchronous method) or a MethodNameAsyncCancel method (if there are multiple asynchronous methods).
实现了基于事件的异步模式的类,会有一个CancelAsync方法(如果仅有一个异步方法的话)或者有一个MethodNameAsyncCancel方法(如果有多个异步方法的话)
Methods that allow multiple invocations take a userState parameter, which can be used to track the lifetime of each task.
带有userState参数的多次方法调用,可以用来追踪每个任务的生命周期
CancelAsync takes a userState parameter, which allows you to cancel particular pending tasks.
CancelAsync方法有一个userState参数,确保你可以取消指定的挂起的任务
Methods that support only a single pending operation at a time, like Method1Async(string param), are not cancelable.
一次仅支持一个单独的挂起操作方法,就像Method1Async(string param)一样,是不可以取消的
- 5.Receiving Progress Updates and Incremental Results接收进度更新以及增量结果
A class that adheres to the Event-based Asynchronous Pattern may optionally provide an event for tracking progress and incremental results.
符合基于事件的异步模式的类为了跟踪进度和增量结果,会提供事件。
This will typically be named ProgressChanged or MethodNameProgressChanged, and its corresponding event handler will take a ProgressChangedEventArgs parameter.
事件通常被命名为ProgressChanged或MethodNameProgressChanged,并且会有一个和事件处理器相对应的ProgressChangedEventArgs事件参数
The event handler for the ProgressChangedevent can examine the ProgressChangedEventArgs.ProgressPercentage property to determine what percentage of an asynchronous task has been completed.
ProgressChangedevent的事件处理器可以通过ProgressChangedEventArgs.ProgressPercentage属性来检查异步任务完成的百分比
This property will range from 0 to 100, and it can be used to update the Value property of a ProgressBar.
此属性的范围从0到100,它可以用来更新进度条的Value属性
If multiple asynchronous operations are pending, you can use the ProgressChangedEventArgs.UserState property to distinguish which operation is reporting progress.
如果多个异步操作挂起,你可以通过ProgressChangedEventArgs.UserState属性来区分是哪一个操作在报告进度。
Some classes may report incremental results as asynchronous operations proceed.
有些类可以在异步操作进行的同时,报告增量结果
These results will be stored in a class that derives from ProgressChangedEventArgs and they will appear as properties in the derived class.
结果被保存在一个从ProgressChangedEventArgs派生的类中,增量结果作为派生类的属性出现
You can access these results in the event handler for the ProgressChanged event, just as you would access the ProgressPercentage property.
你可以在ProgressChanged事件对应的事件处理器中访问增加结果,就像你访问ProgressPercentage属性一样
If multiple asynchronous operations are pending, you can use the UserState property to distinguish which operation is reporting incremental results.
如果有多个异步操作挂起,你可以通过UserState属性来区分哪一个操作正在报告增量结果