Visual Studio在处理异常异常时出现异常,处理异常对话框

Visual Studio在处理异常异常时出现异常,处理异常对话框

问题描述:

我的代码调用当前未运行的WCF服务。所以我们应该期待EndPointNotFoundException。使用声明尝试Close()故障的连接,导致除外的CommunicationObjectFaultedException。该例外被捕获在使用块周围try catch块:Visual Studio在处理异常异常时出现异常,处理异常对话框

class Program 
{ 
    static void Main() 
    { 
     try 
     { 
      using (ChannelFactory<IDummyService> unexistingSvc = new ChannelFactory<IDummyService>(new NetNamedPipeBinding(), "net.pipe://localhost/UnexistingService-" + Guid.NewGuid().ToString())) 
      { 
       using (IClientChannel chan = (unexistingSvc.CreateChannel() as IClientChannel)) 
       { 
        (chan as IDummyService)?.Echo("Hello"); 
       } 
      } 
     } 
     catch (EndpointNotFoundException ex) 
     { 
      Console.WriteLine("Expected"); 
     } 
     catch (CommunicationObjectFaultedException ex) 
     { 
      Console.WriteLine("Expected: caused by closing channel that has thrown EndPointNotFoundException"); 
     } 
    } 
} 

注的服务端点使用新鲜的Guid所以它永远不会有一个服务的聆听。

IDummyService是:

[ServiceContract] 
interface IDummyService 
{ 
    [OperationContract] 
    string Echo(string e); 
} 

这将导致Visual Studio调试器(Visual Studio的专业2017年15.4.1)与 “异常未处理” 弹出打破: Screen shot: Debugger breaking with Exception Unhandled popup 异常上的Visual Studio休息是System.ServiceModel.CommunicationObjectFaultedException其中在代码中捕获。

步进继续执行表明已到达catch(CommunicationObjectFaultedException ex)。使用LinqPad运行演示也表明,异常被捕获如预期。

我也试过明确(双)关闭通道,而不是使用using - 阻塞的:

class Program 
{ 
    static void Main() 
    { 
     try 
     { 
      using (ChannelFactory<IDummyService> unexistingSvc = new ChannelFactory<IDummyService>(new NetNamedPipeBinding(), "net.pipe://localhost/UnexistingService-" + Guid.NewGuid().ToString())) 
      { 
       IDummyService chan = null; 
       try 
       { 
        chan = unexistingSvc.CreateChannel(); 
        chan.Echo("Hello"); 
       } 
       catch (EndpointNotFoundException ex) 
       { 
        Console.WriteLine($"Expected: {ex.Message}"); 
       } 
       finally 
       { 
        try 
        { 
         (chan as IClientChannel)?.Close(); 
        } 
        catch (CommunicationObjectFaultedException ex) 
        { 
         Console.WriteLine($"Caused by Close: {ex.Message}"); 
        } 
       } 
      } 
     } 
     catch (EndpointNotFoundException ex) 
     { 
      Console.WriteLine("Expected"); 
     } 
     catch (CommunicationObjectFaultedException ex) 
     { 
      Console.WriteLine("Expected: caused by closing channel that has thrown EndPointNotFoundException"); 
     } 
    } 
} 

这仍然使得调试器在Close声明打破。

我的例外设置有System.ServiceModel.CommunicationObjectFaultedException未选中。 (当它被检查时,Visual Studio按预期中断并且使用“Exception Thrown”对话框而不是“Exception Unhandled”对话框)。

当我启用“选项”\“调试”\“常规”\“启用只是我的代码”调试器不会中断。然而,我有async方法,其中异常应该离开我的代码,我后来发现 await。对于这些方法,我需要“启用只是我的代码”取消选中;见Stop visual studio from breaking on exception in Tasks

继续“使用新的异常助手”已禁用(由Jack Zhai-MSFT建议)的Visual Studio仍然打破了,它显示 Screenshot exception dialog when "Using the New Exception Helper" is disabled 对话框提供了一些额外的信息:

的异常没有被捕获它穿过前一个管理/本地边界。

我怀疑使用块可能会引入此托管/本机边界。

是什么导致调试器错误地中断以及如何使调试器既不中断也不处理CommunicationObjectFaultedException s也不对后来的处理器async异常?

+1

如果在VS2017的TOOLS-> OPTION-> Debugging-> General下禁用调试选项“使用新的异常帮助程序”,那么结果如何? –

+0

@ JackZhai-MSFT我使用“使用新的例外助手”进行了测试,并将结果包括在问题中。旧的例外对话为解决问题提供了一些新的途径。 –

+0

@ JackZhai-MSFT谢谢,您的建议帮助我通过正确的设置解决问题。现在发布答案。 –

Close() -ing一个FaultedIClientChannel导致CommunicationObjectFaultedException

public void Close(TimeSpan timeout) 
{ 
    ... 
    switch (originalState) 
    { 
     case CommunicationState.Created: 
     case CommunicationState.Opening: 
     case CommunicationState.Faulted: 
      this.Abort(); 
      if (originalState == CommunicationState.Faulted) 
      { 
       throw TraceUtility.ThrowHelperError(this.CreateFaultedException(), Guid.Empty, this); 
      } 
      break; 
     ... 
    } 
    ... 
} 

- (参见在.NET framework 4.7 reference sourceCommunicationObject.Close(TimeSpan) line #299)。

using - 块被转换为try { ... } finally { Dispose(); }Dispose()当块被留下时调用Close()。由CreateChannel()返回的代理通过RealProxysrc)和RemotingServices.CreateTransparentProxy()执行,这些代理结合了托管代码和非托管代码,这些代码可能会导致异常通过边界。

的设置(在工具 - >选项> Debugger->一般)的组合:

  • ☑休息的时候例外交叉的AppDomain或管理/本地边界
  • ☐启用仅我的代码

导致Visual Studio来打破要么显示:新的非模态的异常弹出“异常未处理”: Screenshot: Visual Studio: Exception Unhandled (New Exception Handler)或模态对话框: Screenshot: Visual studio breaking on exception that crosses AppDomain or managed/native boundary

CommunicationObjectFaultedException从'不是我的代码'开始;它跨越了托管/非托管或AppDomain边界,同时仍处于“不是我的代码”中;并最终输入'我的代码',它由catch -block处理(但Visual Studio已经停止了此时的迁移)。
由于异常在“不是我的代码”中开始,并且在穿越边界时仍然存在,因此选择“启用我的代码”选项会使Visual Studio在异常时不会中断异常,即使它穿过AppDomain或管理/非管理边界。
取消选择“当异常跨AppDomain或托管/本地边界时中断”也会导致Visual Studio不会中断异常。

这给出了两个解决方案/变通方法

+0

我有EndPointNotFoundException相同的问题。这个设置为我修好了!谢谢。 – z00mable

新的异常功能在VS2017中,我们可以在工具 - >选项 - >调试 - >常规下禁用调试选项“使用新的异常帮助程序”,它可以为您提供旧的异常消息,您可以访问它。

旧异常消息表明异常越过管理/天然边界: Screenshot exception dialog when "Using the New Exception Helper" is disabled

检查“打破时例外交叉应用程序域或管理/天然边界”下工具 - >选项 - > Debugging->常规。禁用“异常中断时跨越AppDomain或管理/本地边界”以避免Visual Studio突破OP的情况(请小心,因为这也会禁止打破异常跨越AppDomain或管理/本地边界的其他情况)。