《C#多线程编程实战(原书第2版)》——3.2 在线程池中调用委托

简介:

本节书摘来自华章出版社《C#多线程编程实战(原书第2版)》一书中的第3章,第3.2节,作者(美)易格恩·阿格佛温(Eugene Agafonov),黄博文 黄辉兰 译,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.2 在线程池中调用委托

本节将展示在线程池中如何异步的执行委托。另外,我们将讨论一个叫做异步编程模型(Asynchronous Programming Model,简称APM)的方式,这是.NET历史中第一个异步编程模式。

3.2.1 准备工作

为了学习本节,你需要安装Visual Studio 2015。除此之外无需其他准备。本节的源代码放置在BookSamplesChapter3Recipe1目录中。

3.2.2 实现方式

请执行以下步骤来了解如何在线程池中调用委托:

1.启动Visual Studio 2015。新建一个C#控制台应用程序项目。

2.在Program.cs文件中加入以下using指令:


740dda60018aaa3e3f8d820d304feff66401fc0a

3.在Main方法下面加入以下代码片段:


6db22f34edc7485711a129c6c6c19354e6102c24

4.在Main方法中加入以下代码片段:


2230a1716522bf36637c8e5914e6a24b61e9c76e


cc6ae629ddaed43321b1ff9abe762e81f3499b5d

5.运行程序。

3.2.3 工作原理

当程序运行时,使用旧的方式创建了一个线程,然后启动它并等待完成。由于线程的构造函数只接受一个无任何返回结果的方法,我们使用了lambda表达式来将对Test方法的调用包起来。我们通过打印出Thread. CurrentThread.IsThreadPoolThread属性值来确保该线程不是来自线程池。我们也打印出了受管理的线程ID来识别代码是被哪个线程执行的。

然后定义了一个委托并调用BeginInvoke方法来运行该委托。BeginInvoke方法接受一个回调函数。该回调函数在异步操作完成后会被调用,并且一个用户自定义的状态会传给该回调函数。该状态通常用于区分异步调用。结果,我们得到一个实现了IAsyncResult接口的result对象。BeginInvoke立即返回了结果,当线程池中的工作者线程在执行异步操作时,仍允许我们继续其他工作。当需要异步操作的结果时,可以使用BeginInvoke方法调用返回的result对象。我们可以使用result对象的IsCompleted属性轮询结果。但是在本例子中,使用的是AsyncWaitHandle属性来等待直到操作完成。当操作完成后,会得到一个结果,可以通过委托调用EndInvoke方法,传递委托参数和IAsyncResult对象。

事实上使用AsyncWaitHandle并不是必要的。如果注释掉r.AsyncWaitHandle.WaitOne,代码照样可以成功运行,因为EndInvoke方法事实上会等待异步操作完成。调用EndInvoke方法(或者针对其他异步API的EndOperationName方法)是非常重要的,因为该方法会将任何未处理的异常抛回到调用线程中。当使用这种异步API时,请确保始终调用了Begin和End方法。

当操作完成后,传递给BeginInvoke方法的回调函数将被放置到线程池中,确切地说是一个工作者线程中。如果在Main方法定义的结尾注释掉Thread.Sleep方法调用,回调函数将不会被执行。这是因为当主线程完成后,所有的后台线程会被停止,包括该回调函数。对委托和回调函数的异步调用很可能会被同一个工作者线程执行。通过工作者线程ID可以容易地看出。

使用BeginOperationName/EndOperationName方法和.NET中的IAsyncResult对象等方式被称为异步编程模型(或APM模式),这样的方法对称为异步方法。该模式也被应用于多个.NET类库的API中,但在现代编程中,更推荐使用任务并行库(Task Parallel Library,简称TPL)来组织异步API。第4章将会讨论该主题。

相关文章
|
1月前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结
|
1月前
|
安全 编译器 C#
C#学习相关系列之多线程---lock线程锁的用法
C#学习相关系列之多线程---lock线程锁的用法
|
1月前
|
C#
C#学习相关系列之多线程---ConfigureAwait的用法
C#学习相关系列之多线程---ConfigureAwait的用法
|
1月前
|
C#
C#学习相关系列之多线程---TaskCompletionSource用法(八)
C#学习相关系列之多线程---TaskCompletionSource用法(八)
|
1月前
|
Java C#
C#学习系列相关之多线程(五)----线程池ThreadPool用法
C#学习系列相关之多线程(五)----线程池ThreadPool用法
|
30天前
|
存储 算法 Java
【C/C++ 线程池设计思路】 深入探索线程池设计:任务历史记录的高效管理策略
【C/C++ 线程池设计思路】 深入探索线程池设计:任务历史记录的高效管理策略
74 0
|
2天前
|
安全 算法 Java
JavaSE&多线程&线程池
JavaSE&多线程&线程池
16 7
|
27天前
|
Java 测试技术 Python
Python开启线程和线程池的方法
Python开启线程和线程池的方法
17 0
Python开启线程和线程池的方法
|
30天前
|
安全 Java 调度
【C/C++ 线程池设计思路 】设计与实现支持优先级任务的C++线程池 简要介绍
【C/C++ 线程池设计思路 】设计与实现支持优先级任务的C++线程池 简要介绍
44 2
|
1月前
|
负载均衡 Java 数据处理
【C++ 并发 线程池】轻松掌握C++线程池:从底层原理到高级应用(三)
【C++ 并发 线程池】轻松掌握C++线程池:从底层原理到高级应用
55 2