[英]Asynchronous network programming with async/await
在过去的几年中,我已经使用异步编程模型和套接字开发了客户端/服务器软件。 MSDN上的此示例尽管复杂化了诸如ManualResetEvents之类的同步机制,但却说明了以下概念:您将BeginXXX()
和EndXXX()
方法对用于连接和流操作。
这样的好处是让线程池根据需要(例如,当接收到数据时)分配线程,而不是每个连接都没有专用线程,这不会扩展。
最近有人提到,也可以使用.NET 4.5中引入的async / await模型来实现此方法,从而使用Tasks并使该情况下不需要APM。 怎么做?
Task Asynchronous Pattern
及其使用的关键字async-await
允许您以“更干净”的方式使用异步I / O(如您所说)。
无需使用BeginXXX
和EndXXX
方法并在彼此之间传递回调,您只需await
返回awaitable的async方法上await
即可(A Task
是其中的一个示例)。
例如,让我们使用HttpClient
进行示例:
public async Task DoGetWebRequestAsync()
{
var httpClient = new HttpClient();
await httpClient.GetAsync(url);
}
要做的是,一旦该方法命中了await
关键字,它将把控制权交还给调用方法,在幕后创建一个状态机(该状态机将负责执行继续,传播异常等),并IO工作完成后,可通过IOCP(由ThreadPool分配的IO完成端口)恢复。
TAP还提供了一种使用TaskFactory.FromAsync
将旧的APM模式转换为TAP的方法:
FileInfo fi = new FileInfo(path);
byte[] data = null;
data = new byte[fi.Length];
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read,
FileShare.Read, data.Length, true);
//Task<int> returns the number of bytes read
Task<int> task = Task<int>.Factory.FromAsync(
fs.BeginRead, fs.EndRead, data, 0, data.Length, null);
编辑:
如何使用async
很简单。 例如,使用FileStream
:
public async Task<byte[]> ReadBufferAsync(string path)
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read,
FileShare.Read, data.Length, true);
// Read some bytes, not all, just for the example.
byte[] buffer = new byte[2048];
await fs.ReadAsync(buffer, 0, buffer.Length);
return buffer;
}
您将方法标记为async
以便可以在其中使用await
关键字,然后仅在读取的方法上await
。
实际上,由Socket
类支持的旧APM使用了特殊的线程池IOCP(“ I / O完成端口”)线程池,而不是在“接收数据时”分配线程,而是将线程实际分配为I / O操作启动 ,但以允许单个线程(或少量线程,例如与系统上的内核一样多的线程)的方式处理大量套接字对象和操作。
至于如何使用新的async
/ await
样式的API,不幸的是Socket
类没有得到任何直接的async
爱。 但是,所有包装程序都做到了。 最简单的替换方法是使用NetworkStream
类,并使用ReadAsync()
和WriteAsync()
,它们是可以等待的方法。
如果您仍然想直接使用Socket
API(本质上),则必须使用等待的实现将其包装起来。 恕我直言,这里是一个很好的资源,它解释了一种可行的方法: 等待套接字操作
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.