尽管异常类型的 catch 块异常升级

Exception escalates despite a catch block of Exceptions type

我有一个要写入数据的 TCP 套接字列表。如果写入失败,我将其从列表中删除并继续。

至少计划是这样。发生的情况是,当客户端断开连接时,SocketException 升级并且程序崩溃,即使该异常已被处理。代码如下:

// sockets is type List<Socket>
foreach (Socket s in sockets)
{
  String jsonString = skeleton.Marshall();
  byte[] jsonBytes = System.Text.Encoding.UTF8.GetBytes(jsonString);

  try
  {
    s.Send(jsonBytes); // boom! System.Net.Sockets.SocketException!
  }
  catch (System.Net.Sockets.SocketException except)
  {
    sockets.Remove(s);
    Console.WriteLine(except.StackTrace);
  }
  catch (Exception except)
  {
    Console.WriteLine(except.StackTrace);
  }
}

我不明白为什么任何异常都可以通过这个。我没有看控制台输出,因为 Visual Studio 清除了异常发生时的内容(至少我在那里没有看到任何有意义的东西)

感谢您的帮助!

编辑

正如 Sebastian Negraszus 所指出的,我不能直接从列表中删除 Socket,所以现在的代码是

List<Socket> remove = new List<Socket>();

// sockets still is of type List<Socket>
foreach (Socket s in sockets)
{
    String jsonString = skeleton.Marshall();
    byte[] jsonBytes = System.Text.Encoding.UTF8.GetBytes(jsonString);

    try
    {
        s.Send(jsonBytes);
    }
    catch (System.Net.Sockets.SocketException except)
    {
        remove.Add(s);
        Console.WriteLine(except.StackTrace);
    }
    catch (Exception except)
    {
        Console.WriteLine(except.StackTrace);
    }
}

foreach (Socket s in remove)
{
    sockets.Remove(s);
}

但是,即使 Socket 没有从列表中删除,它也应该在这里升级。

编辑 2

此代码在事件处理程序中运行,而套接字正在主线程中填充,因此我认为缺少锁定会导致问题。但是加了锁之后,还是报错

主线程:

// ...
sockets = new List<Socket>();
delegateFoo += handlerFunction;
// ...
TcpListener tcpListener = new TcpListener(IPAddress.Any, 20001);
tcpListener.Start();

while (true) {
    Socket s = tcpListener.AcceptSocket();
    lock (sockets) {
        sockets.Add(s);
    }
}

处理函数:

// ...generate skeleton...
lock (sockets)
{
    foreach (Socket s in sockets)
    {
        String jsonString = skeleton.Marshall();
        byte[] jsonBytes = System.Text.Encoding.UTF8.GetBytes(jsonString);

        try
        {
            s.Send(jsonBytes);
        }
        catch (System.Net.Sockets.SocketException except)
        {
            remove.Add(s);
            Console.WriteLine(except.StackTrace);
        }
        catch (Exception except)
        {
            Console.WriteLine(except.StackTrace);
        }
    }

    foreach (Socket s in remove)
    {
        sockets.Remove(s);
    }
}

虽然运气不好,异常仍然升级(至少我是这么认为的,程序在 VS 中中断,这个小 window 出现说 "SocketException occured"(我使用德语版本,所以措辞可能不同)。 该错误可以通过使用腻子连接两次并关闭两个腻子之一来触发。下次调用 Send() 时 - boom.

编辑 3:异常详细信息

抱歉,这些是德语的。翻译:

是的,我的程序中只发送了一次。

编辑 4:Visual Studio 古怪

好吧,Visual Studio 很奇怪。我可以取消选中 "break on Exceptions of this type" 复选框,然后它就会继续。所以异常并没有升级,但是还是让程序停止了。

我不明白你为什么要在默认情况下中断已处理的异常。我想如果我取消选中程序就会出错。如果您有更好的解决方案,我很乐意采纳您的回答。

我假设 socketsList<T>?当仍在 foreach 循环内时,您不能使用 sockets.Remove(s); 修改列表,因为这会使枚举器无效。下一次迭代导致 InvalidOperationException.

取消选中 "break on exceptions of this type"(或任何英文名称)。之后工作正常。