2010-02-08 69 views
4

我公司为GUI应用程序提供网络组件(DLL)。为什么这个SocketException未被泛型catch例程捕获?

它使用定时器来检查断开连接。如果要重新连接,它要求:

internal void timClock_TimerCallback(object state) 
{ 
    lock (someLock) 
    { 
    // ... 
    try 
    { 
     DoConnect(); 
    } 
    catch (Exception e) 
    { 
     // Log e.Message omitted 
     // Raise event with e as parameter 
     ErrorEvent(this, new ErrorEventArgs(e)); 
     DoDisconnect(); 
    } 
    // ... 
    } 
} 

所以,问题是,在DoConnect()例程SocketException抛出(而不是抓)的内部。我会假设catch(Exception e)应该捕获所有的异常,但是不知何故SocketException并没有被捕获并且显示给GUI应用程序。

protected void DoConnect() 
{ 
    // 
    client = new TcpClient(); 
    client.NoDelay = true; 
    // In the following call the SocketException is thrown 
    client.Connect(endPoint.Address.ToString(), endPoint.Port); 
    // ... (login stuff) 
} 

该文档证实SocketException扩展了Exception。 是出现了堆栈跟踪是:

TcpClient.Connect() -> DoConnect() -> timClock_TimerCallback 

所以没有抛出异常的try/catch块之外。

任何想法,为什么它不工作?

+0

只有在连接了调试器或始终运行代码时才会出现此问题吗?此外catch还可以捕获try块中的所有异常 - 但是如果您的DoConnect执行了一次fire并忘记了该异常,则DoConnect将返回并且处理将继续导致异常被您的预期处理程序取消处理。 – cfeduke 2010-02-08 15:42:13

回答

0

我写了一个小程序,无法重现,一个SocketException被捕获到TimerCallback中就好了。

所以我建议你重新考虑你的分析,问题可能不是你认为的问题。几点建议:

  • 在定时器外运行。 T帽子将线程从线程中取出。
  • 在调试器中运行它。异常真的发生在哪里?
  • 逐步完成异常处理。 ErrorEvent正在做它应该做的事情吗?
+0

谢谢,我问了这个问题,因为我也没有解释为什么会发生这种情况,并希望获得新的灵感。我不认为它是可重现的(如你的程序所示),但它显然发生了,所以我必须进行调查。 – Tarnschaf 2010-02-08 19:25:55

+0

该行为仍然不可重现,因此我添加了调试代码并将等待它再次发生。接受你的答案,因为它是最直接的。 – Tarnschaf 2010-02-09 10:10:03

1

如果ErrorEvent确实会引发另一个异常(根据评论),那么DoDisconnect()永远不会执行。

否则,你看到的例外可能是未来的形式DoDisconnect()

+0

请参阅添加的堆栈跟踪为什么这不能成为解决方案 – Tarnschaf 2010-02-08 15:42:35

0

你能张贴DoConnect()代码?

也可以尝试: 你可以在DoConnect()中捕获它吗? 尝试捕捉特定的异常,而不仅仅是泛型。 如果您使用调试模式,它会如何反应?

+0

读取留给其他人的回复,保持原样,但添加一个SECOND catch块来捕获SocketExeption或Win32Exception。 – Roast 2010-02-08 15:43:31

+0

根据请求添加了DoConnect()方法。你是否也有解释你的想法,因为SocketException扩展了Win32Exception扩展了ExternalException extends Exception? – Tarnschaf 2010-02-08 15:46:03

+0

有两个原因,.NET 1.1 win32exception不是从Exception派生的。否则,您的异常不会被捕获,因为它在DoConnect内启动的另一个线程上引发。 – Roast 2010-02-08 15:55:01

0

您的timClock_TimerCallback不会在catch语句想要捕获异常的同一线程中调用。您应该捕获timClock_TimerCallback中的异常,然后调用一个调用自身的方法,然后在正确的线程中重新抛出异常。

不知道这会起作用,但你可以试试看。

+1

这听起来很有趣..但是从TimerCallback线程调用TcpClient.Connect()在哪里也捕获驻留,其他线程可能涉及? – Tarnschaf 2010-02-08 15:56:59

+0

糟糕,我通过DoConnect调用了timClock_TimerCallback,但那显然是错误的。恐怕我的回答不会帮助你。 – 2010-02-09 08:18:05

相关问题