【发布时间】:2015-01-04 23:24:39
【问题描述】:
在下面的代码中,我从Main() 调用Receive(),然后调用Async BeginReceive(),并在后台线程中完成接收数据。
问题:对于第一次读取,BeginReceive 成功并附加了 StringBuilder。但是,当再次调用时,永远不会达到if(bytesread>0) 条件,因此我永远不会对收到的数据采取行动。
我希望 BeginReceive 处理多个读取,并且(我认为这与线程有关)我希望 Main() 函数始终侦听来自客户端的新命令(不是新连接,我想保持相同的套接字)。这甚至可能吗?
尝试解决方案:我添加了 ManualResetEvent 以试图阻止 Main() 函数在另一个线程中进行异步读取之前退出。
Main()中的相关代码:
Receive(server); //await instructions from the client
done.WaitOne(); //This is a ManualResetEvent.
Console.ReadLine();
方法定义:
public static void Receive(Socket server)
{
try
{
SocketArgs sockargs = new SocketArgs();
sockargs.handler = server;
server.BeginReceive(sockargs.buffer, 0, sockargs.buffersize, 0, new AsyncCallback(ReceiveCallBack), sockargs);
}
catch
{
}
}
public static void ReceiveCallBack(IAsyncResult ia)
{
try
{
SocketArgs sockargs = (SocketArgs)ia.AsyncState;
Socket server = sockargs.handler;
int BytesRead = server.EndReceive(ia);
if (BytesRead > 0)
{
//Continue reading data.
sockargs.sb.Append(Encoding.ASCII.GetString(sockargs.buffer, 0, BytesRead));
MessageBox.Show(sockargs.sb.ToString());
server.BeginReceive(sockargs.buffer, 0, sockargs.buffersize, 0, new AsyncCallback(ReceiveCallBack), sockargs);
}
else
{ //Do stuff with sb.ToString()
done.Set();
}
}
catch(Exception e)
{
MessageBox.Show(e.ToString());
}
}
【问题讨论】:
-
您的
ReceiveCallback是否执行过第二次?如果没有,你确定客户端发送了额外的数据吗? -
好吧,客户端并没有发送大量数据,只是您可以一次读取的数据。我的问题是,第二次,它应该返回读取的零字节,然后执行我的处理代码。但是,在第二次读取调用中似乎没有达到这一点。
-
如果客户端断开连接,您只会获得零字节读取。我有一个blog post,它更详细。
-
好吧,就这样,我需要在主函数中做什么,让处理程序 sock 永远等待更多数据?我尝试了手动重置事件,但奇怪的是它仍然有退出。
-
即使 MRE 没有阻塞(如果设置了就会出现这种情况),那么
ReadLine肯定会。
标签: c# multithreading sockets asynchronous