在使用异步套接字的MSDN示例中,套接字中的数据接收是通过从由BeginReceive调用的回调处理程序中反复调用异步BeginReceive来完成的:
private static void ReceiveCallback( IAsyncResult ar ) {
//...Skipped...
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
new AsyncCallback(ReceiveCallback), state);
} else {
// ...Skipped...
}
http://msdn.microsoft.com/zh-CN/library/bbx2eya8(v=vs.110).aspx
是否有必要从已经在单独线程中执行的处理程序再次进行异步调用?可以在此处理程序的循环中简单地使用Receive吗?就像是:
while (bytesRead) {
bytesRead = client.Receive(state.buffer, 0, client.Available,
SocketFlags.None);
// Etc...
}
APM模式的主要目标是避免在等待异步操作结果时阻塞调用线程,从而提高服务器应用程序的可伸缩性。
如果AsyncCallback
您继续Receive
同步地在循环中调用,则仍将阻塞初始操作BeginReceive
已完成的IOCP线程。这对于客户端UI应用程序可能是可以的,因为您可能不需要担心ThreadPool
饥饿,但这对于服务器端应用程序绝对不是一个好主意,在服务器端应用程序中,被阻塞的线程可能会服务于其他传入的客户端请求。
请注意,在C#5.0 / .NET 4.5及更高版本中,APM被认为是旧版。您可以使用async/await
和new Task-based Asynchronous Pattern (TAP)
模式,这大大简化了异步代码的开发,例如:
async Task<string> ReadAllAsync()
{
var sb = new StringBuffer();
using (var tcp = new TcpClient())
{
await tcp.ConnectAsync(IPAddress.Parse("localhost"), 8080).ConfigureAwait(false);
var buffer = new byte[1024];
using (var stream = tcp.GetStream())
{
var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (0 == bytesRead)
break;
sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
}
}
return sb.ToString();
}
如果由于某些原因您不想使用它NetworkStream.ReadAsync
,则可以使用以下命令将APM样式的套接字API包装为TAP Task.FromAsync
:
public static class SocketsExt
{
static public Task ReceiveDataAsync(
this TcpClient tcpClient,
byte[] buffer)
{
return Task.Factory.FromAsync(
(asyncCallback, state) =>
tcpClient.Client.BeginReceive(buffer, 0, buffer.Length,
SocketFlags.None, asyncCallback, state),
(asyncResult) =>
tcpClient.Client.EndReceive(asyncResult),
null);
}
static public async Task<Int32> ReceiveInt32Async(
this TcpClient tcpClient)
{
var data = new byte[sizeof(Int32)];
await tcpClient.ReceiveDataAsync(data).ConfigureAwait(false);
return BitConverter.ToInt32(data, 0);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句