Dan*_*han 8 .net c# multithreading networkstream
我需要读取NetworkStream哪个会随机发送数据,数据包的大小也会不断变化.我正在实现一个多线程应用程序,其中每个线程都有自己的流来读取.如果流上没有数据,应用程序应该一直等待数据到达.但是,如果服务器完成了发送数据并终止了会话,那么它应该退出.
最初我使用该Read方法从流中获取数据,但它用于阻塞线程并一直等待直到数据出现在流上.
MSDN上的文档建议,
如果没有可用于读取的数据,则Read方法返回0.如果远程主机关闭连接,并且已收到所有可用数据,则Read方法立即完成并返回零字节.
但在我的情况下,我从来没有得到Read返回0并优雅退出的方法.它只是无限期地等待.
在我的进一步调查中,我遇到了BeginRead监视流并在接收数据时异步调用回调方法.我也试图使用这种方法寻找各种实现,但是,我无法确定何时使用BeginRead是有益的而不是Read.
在我看来,它BeginRead具有异步调用的优势,它不会阻止当前线程.但是在我的应用程序中,我已经有了一个单独的线程来读取和处理来自流的数据,所以这对我来说没什么大不了的.
任何人都可以帮我理解等待和退出机制,
BeginRead它有什么不同Read?
实现所需功能的最佳方法是什么?
djd*_*d87 12
我使用BeginRead,但继续阻止线程使用WaitHandle:
byte[] readBuffer = new byte[32];
var asyncReader = stream.BeginRead(readBuffer, 0, readBuffer.Length,
null, null);
WaitHandle handle = asyncReader.AsyncWaitHandle;
// Give the reader 2seconds to respond with a value
bool completed = handle.WaitOne(2000, false);
if (completed)
{
int bytesRead = stream.EndRead(asyncReader);
StringBuilder message = new StringBuilder();
message.Append(Encoding.ASCII.GetString(readBuffer, 0, bytesRead));
}
Run Code Online (Sandbox Code Playgroud)
基本上,它允许使用the的异步读取超时,如果读取在设置的时间内完成(在这种情况下)WaitHandle,则给出一个布尔值().completed2000
这是我从我的一个Windows Mobile项目复制并粘贴的完整流阅读代码:
private static bool GetResponse(NetworkStream stream, out string response)
{
byte[] readBuffer = new byte[32];
var asyncReader = stream.BeginRead(readBuffer, 0, readBuffer.Length, null, null);
WaitHandle handle = asyncReader.AsyncWaitHandle;
// Give the reader 2seconds to respond with a value
bool completed = handle.WaitOne(2000, false);
if (completed)
{
int bytesRead = stream.EndRead(asyncReader);
StringBuilder message = new StringBuilder();
message.Append(Encoding.ASCII.GetString(readBuffer, 0, bytesRead));
if (bytesRead == readBuffer.Length)
{
// There's possibly more than 32 bytes to read, so get the next
// section of the response
string continuedResponse;
if (GetResponse(stream, out continuedResponse))
{
message.Append(continuedResponse);
}
}
response = message.ToString();
return true;
}
else
{
int bytesRead = stream.EndRead(asyncReader);
if (bytesRead == 0)
{
// 0 bytes were returned, so the read has finished
response = string.Empty;
return true;
}
else
{
throw new TimeoutException(
"The device failed to read in an appropriate amount of time.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
异步 I/O 可用于在更少的线程中实现相同数量的 I/O。
正如您所注意到的,现在您的应用程序每个流都有一个线程。这对于少量连接是可以的,但是如果您需要一次支持 10000 个呢?使用异步 I/O,这不再是必要的,因为读取完成回调允许传递上下文以识别相关流。您的读取不再阻塞,因此每个流不需要一个线程。
无论您使用同步还是异步 I/O,都有一种方法可以检测和处理相关 API 返回码上的流关闭。 如果套接字已关闭,则BeginRead应失败并显示 IOException。异步读取挂起时的关闭将触发回调,然后EndRead会告诉您播放状态。
当你的应用调用BeginRead时,系统会等待直到收到数据或者出现错误,然后系统会使用一个单独的线程来执行指定的回调方法,并在EndRead上阻塞,直到提供的NetworkStream读取数据或者抛出异常。
| 归档时间: |
|
| 查看次数: |
15272 次 |
| 最近记录: |