2011-12-29 132 views
2

我有TcpListener,当关闭导致所有正在进行的客户端在尝试呼叫EndAcceptTcpClient时抛出以下异常。在TcpListener完全关闭之前,我可以使用更优雅的模式来允许所有现有的客户端连接完成吗?需要一个更优雅的模式来关闭TcpListener

System.ObjectDisposedException:无法访问处置的对象。 对象名称:'System.Net.Sockets.Socket'。在 System.Net.Sockets.Socket.EndAccept(IAsyncResult的asyncResult)在 System.Net.Sockets.TcpListener.EndAcceptTcpClient(IAsyncResult的 asyncResult)

这里是监听设置的一个示例:

​​
requestListener = new TcpListener(endPoint); 

requestListener.Start(1000); 

requestListener.BeginAcceptTcpClient(ServiceRequestInstanceHandler, null); 

当我试图关闭监听我拨打以下。这就是导致上述例外的原因。

if (_requestListener != null) 
{ 
    _requestListener.Stop(); 
} 

这里是通过调用听众Stop()方法

private void ServiceRequestInstanceHandler(IAsyncResult result) 
{ 
    try 
    { 
     using (TcpClient client = _requestListener.EndAcceptTcpClient(result)) 
     { 
      ProcessRequest(client); 
      client.Close(); 
     } 

     //Prepare to accept the next message 
     _requestListener.BeginAcceptTcpClient(ServiceRequestInstanceHandler, null); 
    } 
    catch (Exception ex) 
    { 
     if (_logger.IsErrorEnabled) 
      _logger.Error("An error occured while processing a service request. ", ex); 
    } 
} 

回答

-1

我相信,以避免错误处理这最终影响的回调代码的例子,你需要在你requestListener对象传递到BeginAcceptTcpClient像这样:

requestListener.BeginAcceptTcpClient(ServiceRequestInstanceHandler, requestListener); 

对于参考:http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.beginaccepttcpclient.aspx

我也亲自出马,重新写你的方法,以允许处理其他客户端,像这样在你的服务器接受新的客户端:

private void ServiceRequestInstanceHandler(IAsyncResult result) 
{ 
try 
    { 
     // You should probably check for a null result here, just in case 
     if(result == null) 
     { 
      throw new Exception("Result is null, cannot continue"); 
     } 
     using (TcpClient client = _requestListener.EndAcceptTcpClient(result)) 
     { 
      // Remember this line returns immediately/does not block 
      _requestListener.BeginAcceptTcpClient(ServiceRequestInstanceHandler, _requestListener); 
      ProcessRequest(client); 
      client.Close(); 
     } 
    } 
    catch (Exception ex) 
    { 
     if (_logger.IsErrorEnabled) 
      _logger.Error("An error occured while processing a service request. ", ex); 
    } 
} 

IIRC,异步的东西在一个单独的线程上运行。

注:我没有测试上面的代码,但它应该解决您的问题:)

HTH

+0

夫妇的问题...(** ** 1)由于'_requestListener'是从来没有'空'这仍然会导致相同的错误不是吗? (** 2 **)即使我在停止它之后将它设置为“null”,也不会阻止我完成我们已经收到的请求,并且删除了我向请求者反馈* *的任何可能性*请求将不会被处理? – JoeGeeky 2011-12-29 13:17:13

+0

@StuartBlacker对不起,我误读了这个。我明白你的意思了,我会做出这样的改变,尽管我仍然没有看到如何处理飞行中的请求。 – JoeGeeky 2011-12-29 13:21:21

+1

@JoeGeeky,代码中的'BeginAcceptTcpClient'有两个参数,回调和状态。在文档中它显示你需要传递'TcpListener',以便它知道哪个TcpListener结束接受。因此,如果您为状态传递null并尝试将其转回,则您正在访问null(在本例中为dispose)对象。再一次,我没有测试过,所以我的记忆可能是错的,但我怀疑是这样。那有意义吗? – 2011-12-29 14:10:35