[英]Replacing Socket.ReceiveAsync with NetworkStream.ReadAsync (awaitable)
我有一個應用程序,它同時生成幾百個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() method called after
. Creating a new task for
. Creating a new task for
StartReceive() . Creating a new task for
would just end up with 300-ish threads, and it seems to do so just by calling
StartReceive()來實現。
在使用NetworkStream
,在我現有代碼上實現新async
和await
關鍵字的正確方法是什么,因此它使用Socket.SendAsync()
和Socket.ReceiveAsync()
使用的線程池來避免必須擁有數百個線程/任務?
以這種方式使用networkstream
比使用beginreceive
i / o完成端口有任何性能優勢?
你在這里一次改變兩件事:異步樣式( SocketAsyncEventArgs
到Task
/ async
)和抽象級別( Socket
到NetworkStream
)。
由於您已經熟悉Socket
,我建議只更改異步樣式,並繼續直接使用Socket
類。
Async CTP沒有給Socket
任何async
兼容的方法(這很奇怪;我認為它們被錯誤地遺漏了,並將在.NET 4.5中添加)。
如果您使用我的AsyncEx庫,那么創建自己的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
不會產生新的線程。 我和其他許多人一樣, 在我的博客上寫了一篇async / await簡介 。 async
/ await
允許並發,但這並不一定意味着多線程。 async
/ await
不是一種全新的異步處理形式; 它只是一種表達異步處理的簡單方法 。 它仍然使用下面的IOCP。 async
/ await
性能略低於低級方法; 它的吸引力在於編寫和編寫異步方法的簡易性。 async
/ await
時會看到一些GC壓力增加。 並行團隊的Stephen Toub 寫了一些示例套接字特定的等待 ,可以幫助解決這個問題。 (我建議首先使用簡單的模式,如果你認為有必要,只使用性能增強的方法;但是,如果最終需要它,最好知道它在那里)。 Task
除非您確實需要它們返回void
。 Task
是可以接受的,因此您的方法是可組合的(並且更容易測試); void
更像是“火與忘”。 ConfigureAwait(false)
來告訴其余的async
方法在線程池線程上執行。 我在上面的例子中使用它,以便ProcessData
在線程池線程中執行,就像使用SocketAsyncEventArgs
。 Socket.Connected
沒用。 您需要發送數據以檢測連接是否仍然有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.