- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有一个应用程序可以同时建立几百个 TCP 连接,并从它们接收源源不断的数据流。
private void startReceive()
{
SocketAsyncEventArgs e = new SocketAsyncEventArgs();
e.Completed += receiveCompleted;
e.SetBuffer(new byte[1024], 0, 1024);
if (!Socket.ReceiveAsync(e)) { receiveCompleted(this, e); }
}
void receiveCompleted(object sender, SocketAsyncEventArgs e)
{
ProcessData(e);
if (!Socket.ReceiveAsync(e)) { receiveCompleted(this, e); }
}
我的尝试导致了这样的结果:
private async void StartReceive()
{
byte[] Buff = new byte[1024];
int recv = 0;
while (Socket.Connected)
{
recv = await NetworkStream.ReadAsync(Buff, 0, 1024);
ProcessData(Buff,recv);
}
}
我遇到的问题是调用 StartReceive()
的方法会阻塞,并且无法到达在StartReceive() 之后调用的随附的
StartSend() 方法。为
StartReceive()创建一个新任务最终只会有 300 个左右的线程,而且它似乎只是通过调用
StartReceive()` 来完成。
在使用
NetworkStream
时,在现有代码上实现新的 async
和 await
关键字的正确方法是什么,所以它正在使用Socket.SendAsync()
和 Socket.ReceiveAsync()
正在使用线程池来避免拥有数百个线程/任务?
与使用
beginreceive
的 i/o 完成端口相比,以这种方式使用 networkstream
是否有任何性能优势?
最佳答案
您在这里同时更改了两件事:异步样式(SocketAsyncEventArgs
到 Task
/async
)和抽象级别 ( Socket
到 NetworkStream
)。
既然您已经习惯了Socket
,我建议您只更改异步样式,并继续直接使用Socket
类。
Async CTP 没有给 Socket
任何 async
兼容的方法(这很奇怪;我认为它们被错误地遗漏了,将被添加到 .NET 中4.5).
如果您使用我的 AsyncEx library,创建您自己的 ReceiveAsyncTask
扩展方法(以及其他操作的类似包装器)并不难:
public static Task<int> ReceiveAsyncTask(this Socket socket,
byte[] buffer, int offset, int size)
{
return AsyncFactory<int>.FromApm(socket.BeginReceive, socket.EndReceive,
buffer, offset, size, SocketFlags.None);
}
一旦你这样做了,你的StartReceive
就可以这样写了:
private async Task StartReceive()
{
try
{
var buffer = new byte[1024];
while (true)
{
var bytesReceived = await socket.ReceiveAsyncTask(buffer, 0, 1024)
.ConfigureAwait(false);
ProcessData(buffer, bytesReceived);
}
}
catch (Exception ex)
{
// Handle errors here
}
}
现在,要解决许多小问题:
await
不会生成新线程。我写了an async/await intro on my blog ,和许多其他人一样。 async
/await
允许并发,但这并不一定意味着多线程。
- 数百个线程 可能会出现问题。不过,数百个任务根本不是问题;线程池和 BCL 旨在处理许多任务。
async
/await
并不是一种全新的异步处理形式;这只是一种更简单的方式来表达异步处理。它仍然在底层使用 IOCP。 async
/await
的性能略低于低级方法;它的吸引力在于易于编写和组合异步方法。
- 当切换到
async
/await
时,一个非常繁忙的系统会发现 GC 压力有所增加。并行团队的 Stephen Toub wrote up some example socket-specific awaitables这可以帮助解决这个问题。 (我建议首先使用简单的模式,只有在您认为有必要时才使用性能增强的方法;不过,如果您最终需要它,最好知道它就在那里)。
- 异步方法应该返回
Task
,除非您真的需要它们返回 void
。 Task
是可等待的,因此您的方法是可组合的(并且更容易测试); void
更像是“即发即忘”。
- 您可以调用
ConfigureAwait(false)
来告诉 async
方法的其余部分在线程池线程上执行。我在上面的示例中使用了它,以便 ProcessData
在线程池线程中执行,就像使用 SocketAsyncEventArgs
时一样。
Socket.Connected
没用。 You need to send data to detect if the connection is still valid.
关于c# - 将 Socket.ReceiveAsync 替换为 NetworkStream.ReadAsync(可等待),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9733292/
我不确定我是否遗漏了什么或者 SslStream 中确实存在设计缺陷(可能还有其他可以包装内部流的流类)。 考虑这个伪代码: MyStream { Task ReadAsync() { ...
一段时间以来我一直在思考这个问题(并且知道这很愚蠢)。 我正在下载带有显示正常的 ProgressBar 的文件,但如何从 ReadAsync 流中获取数据进行保存? public static re
如果您不输入任何输入,为什么下面的代码永远不会完成,为什么即使在取消标记被取消后它仍然响应按下的键? // Set up a cancellation token var cancellationSo
我有以下代码(_ns 是一个 NetworkStream) await GetResponse(_ns); btnSend.Enabled = true; private async Task Get
我有一个 C# TcpClient 来异步读取数据。简化代码如下: public async Task StartReading(CancellationToken token) { // T
我以前使用过串行端口及其原始方法,如 BytesToRead、Read 和 Write。据说这些是不可靠的,我有很多忙等待我试图切换到它的异步方法。 我需要使用 2 个不同的超时时间从串口读取数据。第
我正在尝试使用 NetworkStream.ReadAsync() 来读取数据,但我找不到如何在调用后取消 ReadAsync()。对于背景,NetworkStream 由连接的 BluetoothC
当使用“SocketAsyncEventArgs”类和 ReadAsync 时,我应该将读取缓冲区放在哪里以及将发送缓冲区放在哪里?或者我只能一次阅读或发送而不是两者?我有点困惑。 最佳答案 我认为您
我正在尝试将下面的类转换为延迟返回文件。 public class ObservableFile2 : IObservable { private readonly IObservable s
试一试。使用单个按钮和按钮单击事件的以下代码设置新的 Windows 窗体应用程序: private async void button1_Click(object sender, EventArgs
当 NamedPipeServer 流从管道中读取任何数据时,它不会对 CancellationTokenSource.Cancel() 使用react 这是为什么? 如何限制我在服务器中等待来自客户
我正在使用 NetworkStream 和 TcpClient。 首先我设置我的 tcp 客户端: tcp = new TcpClient(AddressFamily.InterNetwork
NetworkStream.ReadAsync 什么时候任务完成?一旦接收到指定长度的数据? 如果是,它会返回 0 吗?然后 CancellationToken可以用作 ReadTimeout ,这是
在samples for the Cosmos DB SQL API , Database.ReadAsync() 有多种用途这似乎没有做任何有用的事情。该方法文档中的第二个注释并没有真正说明它可能用
在samples for the Cosmos DB SQL API , Database.ReadAsync() 有多种用途这似乎没有做任何有用的事情。该方法文档中的第二个注释并没有真正说明它可能用
我正在尝试在 .net 中使用 SerialPort 类。 我选择让我的服务保持异步,所以我在 SerialPort.BaseStream 上使用异步方法。 在我的异步方法中,我将一个 byte[]
鉴于以下情况: using System; using System.IO; using System.Threading; using System.Threading.Tasks; namespa
当调用 SQL Server 执行实际需要时间的操作时,SqlDataReader.ReadAsync() 会为我同步运行。有没有办法强制它异步运行,或者是我在 Task.Run() 中调用它的唯一选
我可以创建一个 MobileServiceClient 和 GetTable()至InsertAsync ,并查看如何将我的模型插入到 Azure 中的 Easy Table 表中。但是当我 Read
我正在尝试构建具有持久 TCP 连接的可扩展 服务器应用程序。我使用的序列化库是同步的,将其转换为APM会造成很大的开销(我已经测试过了)。 数据包的格式始终是数据包 ID 的一个字节,后跟几个 he
我是一名优秀的程序员,十分优秀!