gpt4 book ai didi

C# 套接字 : synchronous calls within asynchronous ones

转载 作者:行者123 更新时间:2023-12-03 11:58:09 25 4
gpt4 key购买 nike

在 MSDN example使用异步套接字时,套接字中的接收数据是通过从 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/en-us/library/bbx2eya8(v=vs.110).aspx

是否有必要从已经在单独线程中执行的处理程序再次进行异步调用?可以简单地在此处理程序中循环使用 Receive 吗?像这样的东西:

while (bytesRead) {

bytesRead = client.Receive(state.buffer, 0, client.Available,
SocketFlags.None);
// Etc...
}

最佳答案

APM pattern的主要目标是为了避免在等待异步操作结果时阻塞调用线程,从而提高服务器应用程序的可扩展性。

如果在 AsyncCallback 中继续同步调用循环中的 Receive,您仍然会阻塞初始 BeginReceive 所在的 IOCP 线程> 已完成。对于客户端 UI 应用程序来说,这可能没问题,您可能不关心 ThreadPool 饥饿问题,但这对于服务器端应用程序来说肯定不是一个好主意,否则阻塞的线程可能会服务其他传入的客户端请求。

请注意,对于 C# 5.0/.NET 4.5 及更高版本,APM 被视为遗留。您可以使用async/awaitnew 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,您可以使用 Task.FromAsync 将 APM 样式套接字 API 包装为 TAP:

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);
}
}

关于C# 套接字 : synchronous calls within asynchronous ones,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24110473/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com