尽管存在异常类型的catch块,但异常会升级

时间:2015-03-13 14:59:43

标签: c# exception exception-handling

我有一个写入数据的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);
    }
}

运气不好,Exception仍在升级(至少我认为是这样,程序在VS中断,这个小窗口发生了&#34; SocketException出现&#34;(我使用德语版本,所以措辞可能是不同)。 可以通过使用putty连接两次并关闭两个puttys中的一个来触发错误。下一次调用Send() - 繁荣。

编辑3:例外细节

抱歉,这些都是德语。文:

  • &#34; ... ist aufgetreten&#34; =&#34; ...发生&#34;
  • &#34;贝&#34; =&#34; at&#34;
  • message =&#34;现有连接已被主机中止/终止&#34;

    System.Net.Sockets.SocketException ist aufgetreten.
      _HResult=-2147467259
      _message=Eine bestehende Verbindung wurde softwaregesteuert durch den Hostcomputer abgebrochen
      HResult=-2147467259
      IsTransient=false
      Message=Eine bestehende Verbindung wurde softwaregesteuert durch den Hostcomputer abgebrochen
      Source=System
      ErrorCode=10053
      NativeErrorCode=10053
      StackTrace:
       bei System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
      InnerException: 
    

是的,我只在程序中发送一次()。

编辑4:Visual Studio怪异

好的,它的Visual Studio很奇怪。我可以取消选中&#34;打破这种类型的例外&#34;复选框,然后它继续。因此,例外没有升级,但仍然使程序停止。

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:-1)

取消选中“此类异常中断”(或英语中的任何内容)。之后工作正常。