天天看点

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

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

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

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

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

1.启动visual studio 2015。新建一个c#控制台应用程序项目。

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

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

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

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

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

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

5.运行程序。

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

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

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

使用beginoperationname/endoperationname方法和.net中的iasyncresult对象等方式被称为异步编程模型(或apm模式),这样的方法对称为异步方法。该模式也被应用于多个.net类库的api中,但在现代编程中,更推荐使用任务并行库(task parallel library,简称tpl)来组织异步api。第4章将会讨论该主题。

继续阅读