我在我的一个Compact Framework 2.0应用程序中使用TcpClient
。我想从TCP服务器接收一些信息。
由于Compact Framework不支持“大型”框架的超时机制,我正在尝试实现自己的超时功能。基本上,我想做以下事情:
IAsyncResult result = networkStream.BeginRead(buffer, 0, size, ..., networkStream);
if (!result.AsyncWaitHandle.WaitOne(5000, false))
// Handle timeout
private void ReceiveFinished(IAsyncResult ar)
{
NetworkStream stream = (NetworkStream)ar.AsyncState;
int numBytes = stream.EndRead(ar);
// SIGNAL IASYNCRESULT.ASYNCWAITHANDLE HERE ... HOW??
}
我想为Set
调用IAsyncResult.AsyncWaitHandle
,但它没有这样的方法,我不知道将它投射到哪个实现。
如何设置等待句柄?或者通过调用EndRead
自动设置?文档表明我必须自己致电Set
......
感谢您的帮助!
更新
似乎在调用EndRead
时自动设置了等待句柄 - 但它不在文档中。有人可以证实这一点吗?
更新2
在我的示例代码中写了client.BeginRead
。当然,在BeginRead
...
NetworkStream
答案 0 :(得分:2)
我认为您对使用TCP的异步IO有误解。
要启动异步IO,请调用stream.BeginRead()。
在回调中,您在流上调用EndRead。
您不会在代码显示的TcpClient上调用BeginRead。您的应用程序不会发出WaitHandle信号。当等待句柄发出信号时,IO层将调用您的回调,换句话说,当异步读取发生时。
在你的回调中,通常你会在流上再次调用BeginRead,如果你可能会收到更多数据。
您可以在this answer中看到明确的示例。
在开始BeginRead / EndRead舞蹈之前, 您可能想在TcpClient上执行异步连接 - 然后您将使用BeginConnect。但这只做了一次。或者,您可能需要同步连接,在这种情况下,您只需调用TcpClient.Connect()。
示例代码:
private class AsyncState
{
public NetworkStream ns;
public ManualResetEvent e;
public byte[] b;
}
public void Run()
{
NetworkStream networkStream = ...;
byte[] buffer = new byte[1024];
var completedEvent = new ManualResetEvent(false);
networkStream.BeginRead(buffer, 0, buffer.Length,
AsyncRead,
new AsyncState
{
b = buffer,
ns = networkStream,
e = completedEvent
});
// do other stuff here. ...
// finally, wait for the reading to complete
completedEvent.WaitOne();
}
private void AsyncRead(IAsyncResult ar)
{
AsyncState state = ar as AsyncState;
int n = state.ns.EndRead(ar);
if (n == 0)
{
// signal completion
state.e.Set();
return;
}
// state.buffer now contains the bytes read
// do something with it here...
// for example, dump it into a filesystem file.
// read again
state.ns.BeginRead(state.b, 0, state.b.Length, AsyncRead, state);
}