c# - NullReferenceException,C# 套接字 BeginConnect 中的错误?

标签 c# .net sockets nullreferenceexception

我们有一个通过 TCP 套接字与客户端通信的服务器应用程序。运行几周后,它会因无法处理的 NullReferenceException 而崩溃。我已经能够用一个非常小的控制台程序重现异常,但似乎在内部套接字线程池中存在未处理的异常。所以我不能用任何 try/catch block 来处理它,因为它不在我的控制之下。

有没有人对此有任何想法?这是一个框架错误还是我如何在套接字线程池上捕获异常(这样我们的应用程序就不会崩溃)? 这是在几次迭代 (3-10) 之后生成异常的示例代码。重要的是要知道服务器处于离线状态,因此套接字无法连接。使用Visual Studio 2010和.Net Framework 4.0。

internal class Program
{
    private static string host;

    private static Socket socket;

    private static void Main(string[] args)
    {
        Trace.Listeners.Add(new ConsoleTraceListener());

        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        host = "127.0.0.1";
        //aslo the problem is happening whe the host is other network ip address
        //host = "192.168.0.1";

        //when in other thread doesn not crash application
        //Task.Factory.StartNew(() => StartConnecting());

        //also crashing the application
        //Task.Factory.StartNew(() => StartConnecting(), TaskCreationOptions.LongRunning);

        //when it is regular thread the exception occurs
        ///*
        var thread = new Thread(new ThreadStart(StartConnecting));
        thread.Start();
        //*/

        //when it is blocking exception also occurs
        //StartConnecting();
        Console.WriteLine("Press any key to exit ...");
        Console.ReadKey();
    }

    private static void StartConnecting()
    {
        try
        {
            int count = 0;
            while (true)
            {
                try
                {
                    // if i must switch to Socket.Connect(...)?
                    Trace.WriteLine(string.Format("Connect Try {0} begin", ++count));

                    var ar = socket.BeginConnect(host, 6500, new AsyncCallback(ConnectCallback), socket);

                    Trace.WriteLine(string.Format("Connect Try {0} end", count));
                }
                catch (Exception err)
                {
                    Trace.WriteLine(string.Format("[BeginConnect] error {0}", err.ToString()));
                }
                System.Threading.Thread.Sleep(1000);
                //will see the exception more quick
            }
        }
        catch (Exception e)
        {
            Trace.WriteLine(string.Format("[StartConnecting] error {0}", e.ToString()));
        }
    }

    private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        string msg = e.ExceptionObject.ToString();

        Trace.WriteLine(string.Format("[CurrentDomain_UnhandledException] isTerminating={0} error {1}", e.IsTerminating, msg));

        Trace.WriteLine("Exiting process");

        //the other processing threads continue working
        //without problems untill there is thread.sleep
        //Thread.Sleep(10000);
    }

    private static void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            Trace.WriteLine("[ConnectCallback] enter");
            var socket = (Socket)ar.AsyncState;
            socket.EndConnect(ar);

            Trace.WriteLine("[ConnectCallback] exit");
        }
        catch (Exception e)
        {
            Trace.WriteLine(string.Format("[ConnectCallback] error {0}", e.ToString()));
        }
    }
}

应用程序启动后不可避免的会发生崩溃:

[CurrentDomain_UnhandledException] isTerminating=True error System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Net.Sockets.Socket.ConnectCallback()
   at System.Net.Sockets.Socket.RegisteredWaitCallback(Object state, Boolean timedOut)
   at System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(Object state, Boolean timedOut)

最佳答案

您提供的示例代码在不等待异步操作完成的情况下重复调用 BeginConnect

粗略地说,你正在这样做

while(true)
{
    socket.BeginConnect(...);
    Sleep(1000);
}

因此,当您的线程启动时,它首先调用 BeginConnect(),然后等待一秒钟,然后在前一个调用仍在执行时再次调用 BeginConnect()

在我的电脑上,它给了我一个 InvalidOperationException,但我猜异常类型可能取决于 CLR 版本(我使用的是 .NET 4.5.1)。

这里有 3 种不同的解决方案:

  1. 使用Socket.EndConnect()取消异步操作
  2. 使用 IAsyncResult.AsyncWaitHandle.WaitOne() 等待异步操作完成
  3. 不要使用 BeginConnect() 而是使用 Connect()

关于c# - NullReferenceException,C# 套接字 BeginConnect 中的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19524199/

相关文章:

c# GetManifestResourceNames() 什么都不返回

c# - SecureString 密码存储在数据库中

c# - 对于从函数输出参数接收的变量,使用未分配的参数编译器错误?

c# - 无法使用服务帐户在谷歌驱动器上上传图片

c++ - 第二次进行客户端连接时没有服务器 OnAccept 通知

javascript - 是否可以更换 Node.js 网络套接字数据事件监听器?

c - 在 linux 上使用 c 中的套接字将文件从客户端发送到服务器

c# - 未将对象引用设置为对象的实例...错误?

c# - 为什么在 MVC5 中 Optional 参数值会自动填充路由数据?

c# - 在托管应用程序中调用具有命名参数的函数