Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# TcpClient.EndConnect在套接字关闭时引发NullReferenceException_C#_Sockets_Asynchronous_Connection_Tcpclient - Fatal编程技术网

C# TcpClient.EndConnect在套接字关闭时引发NullReferenceException

C# TcpClient.EndConnect在套接字关闭时引发NullReferenceException,c#,sockets,asynchronous,connection,tcpclient,C#,Sockets,Asynchronous,Connection,Tcpclient,我正在尝试使用TcpClient.BeginConnect/TcpClient.EndConnect组合连接到我的服务器。然而,有些事情并没有像它们应该的那样起作用 情况如下: 调用TcpClient.BeginConnect 服务器故意脱机(出于测试目的)-因此无法建立连接 我关闭应用程序(client.close()在以下过程中被调用) TcpClientconnection回调方法在给出IAsyncResult 使用给定的IAsyncResult NullReferenceExcepti

我正在尝试使用
TcpClient.BeginConnect/TcpClient.EndConnect
组合连接到我的服务器。然而,有些事情并没有像它们应该的那样起作用

情况如下:

  • 调用
    TcpClient.BeginConnect
  • 服务器故意脱机(出于测试目的)-因此无法建立连接
  • 我关闭应用程序(
    client.close()
    在以下过程中被调用)
  • TcpClient
    connection回调方法在给出
    IAsyncResult
  • 使用给定的
    IAsyncResult
  • NullReferenceException
    发生在
    EndConnect
  • 由于上一个窗体(窗口)已关闭,应用程序应该退出-但是它不会退出,至少在
    BeginConnect
    操作完成之前不会退出(这很奇怪,因为已经调用了回调)

这里发生的是捕获到
NullReferenceException
。如上图所示,
client
ar
都不是
null
。问题在于,没有提到引发此异常的情况

所以基本上,我不知道发生了什么。问题是我被迫等待应用程序关闭(好像连接操作仍在等待超时)。如果服务器处于联机状态,则可以正常连接和断开连接

在本上下文中
NullReferenceException
是什么意思?如果无法建立连接,如何避免
BeginConnect
操作阻止应用程序关闭


附加说明(在评论中要求):

以下是创建客户机的代码(客户机是一个成员变量:

public void Connect()
{
    try
    {
        lock (connectionAccess)
        {
            if (State.IsConnectable())
            {
                // Create a client
                client = new TcpClient();
                client.LingerState = new LingerOption(false, 0);
                client.NoDelay = true;

                State = CommunicationState.Connecting;

                client.BeginConnect(address, port, onTcpClientConnectionEstablished, null);
            }
            else
            {
                // Ignore connecting request if a connection is in a state that is not connectable 
            }
        }
    }
    catch
    {
        Close(true);
    }
}
此外,关闭方法:

public void Close(bool causedByError)
{
    lock (connectionAccess)
    {
        // Close the stream
        if (clientStream != null)
            clientStream.Close();

        // Close the gateway
        if (client != null)
            client.Close();

        // Empty the mailboxes
        incomingMailbox.Clear();
        outgoingMailbox.Clear();

        State = causedByError ? CommunicationState.CommunicationError : CommunicationState.Disconnected;
    }
}

我遇到了一个类似的错误,并最终使用了此代码。我不确定IASyncResult接口是否支持此错误,但可能有类似的方法来运行此检查。我确实注意到您的ar.AsyncState==null,因此可能尝试从那里开始,即当您正确连接时是否为null

private void connConnectCompleted(AsyncCompletedEventArgs e)
{
    if (e.Error != null)
    {
        // Something didn't work...abort captain
        CloseSocket();
        Console.WriteLine(this.GetType().ToString() + @":Error connecting socket:" +  e.Error.Message);
        return;
    }
    // Do stuff with your connection
}
编辑:很抱歉,我没有意识到我没有发布生成AsyncCompletedEventArgs的内容,这与您正在做的事情更相关。您将看到我为什么怀疑ar.AsyncState为null的原因

private void OnConnect(IAsyncResult asyncResult)
{
    if (OnConnectCompleted == null) return; // Check whether something is using this wrapper
    AsyncCompletedEventArgs args;
    try
    {
        Socket outSocket = (Socket) asyncResult.AsyncState;

        // Complete connection
        outSocket.EndConnect(asyncResult);

        args = new AsyncCompletedEventArgs(null);
        OnConnectCompleted(this, args);
    }
    catch (Exception e)
    {
        args = new AsyncCompletedEventArgs(e.Message);
        OnConnectCompleted(this, args);
    }
}

NullReferenceException
可能是由于
TcpClient.Client
为空

private void OnConnect(IAsyncResult asyncResult)
{
    if (OnConnectCompleted == null) return; // Check whether something is using this wrapper
    AsyncCompletedEventArgs args;
    try
    {
        Socket outSocket = (Socket) asyncResult.AsyncState;

        // Complete connection
        outSocket.EndConnect(asyncResult);

        args = new AsyncCompletedEventArgs(null);
        OnConnectCompleted(this, args);
    }
    catch (Exception e)
    {
        args = new AsyncCompletedEventArgs(e.Message);
        OnConnectCompleted(this, args);
    }
}
如果要遵循for
TcpClient.BeginConnect
并将
TcpClient
对象作为状态对象传递:

 private void onConnEst(IAsyncResult ar)
 {
      try
      {
           TcpClient client = (TcpClient)ar.AsyncState;
           if(client!=null && client.Client!=null)
           {
                client.EndConnect(ar);
           }
      }
      catch(Exception ex){...}
 }
这应该可以处理在回调之前调用
Close()
的情况


回到您的问题—应用程序最终关闭需要多长时间?

这显然是TcpClient类中的一个错误。我也遇到过它。TcpClient.Dispose可能会将客户端字段设置为null,但EndConnect不希望如此。

这是一个错误


您应该收到的是“ObjectDisposedException”,而不是“NullReferenceException”。

InnerException是否提供了有关NULL内容的更多信息?@Tremmors Nope.InnerException为NULL。StackTrace也没有提供帮助(onTcpClientConnectionEstablished>EndConnect):(是的,显然是一个框架错误。如果TcpClient在EndConnect()之前关闭)调用时,它应该抛出ObjectDisposedException。我似乎得到了NullReferenceException,而不是前一两次,然后它将按照预期开始抛出ObjectDisposedException。我建议您只需像处理ObjectDisposedException一样处理它(即。“连接超时/失败/无论您调用Close()”的其他原因是什么。但是,我不知道是否有任何资源可能在这里泄漏,因为EndConnect()未完成。GC可能无法处理任何内容。:)在.NET 4.8中,这一问题是如何解决的?AsyncState用于将一些自定义数据传递给回调方法。我没有这种需要,因此它为null。它不会产生错误。我不理解您的示例(它不完整)。IAsyncResult没有错误,我想您应该提供CloseSocket()的代码方法,因为它是您自己的自定义方法。Othwerise,我不知道您的代码示例会有什么帮助。CloseSocket()只是触发几个事件来通知程序的任何其他部分,然后运行。Close()在套接字上。为什么强制转换ar.AsyncResult?您是指ar.AsyncState吗?无论如何,我的客户端是一个私有成员,因此我不需要将其传递给async方法。我当前无法(即不在工作中)检查TcpClient.Client是否为null。但是,根据我的内存和以前的经验,如果我不调用Client.EndConnect,当我尝试关闭它时,应用程序仍然挂起。它通常与连接超时(约20秒)的持续时间相同。如果我在连接尝试期间不关闭应用程序,BeginConnect将在同一时间失败。Oops-您是对的,
ar.AsycResult
应该是
ar.AsyncState
。进行后期编辑以反映更改。您是否能够发布如何构建TcpClient和BeginConnect?是否在创建之前绑定套接字eginConnect?另外,这并不重要,但你使用的是什么.Net框架?我已经更新了问题以填补缺失的部分。我使用的是.Net 4。虽然我没有准确运行你的代码,但Client.Close()不会花太长时间。我建议注释掉你代码中的TcpClient部分(仅用于测试目的)看看你是否仍然体验到了延迟。除此之外,可能有一些多线程被锁定在<代码>连接访问>代码>中,这会导致延迟,如果你在代码中没有经历延迟,这将是有意义的。欢迎这么做!你可能要考虑精心设计。