Visual Studio在使用未处理的异常对话框处理IS的异常中断

时间:2017-10-20 13:52:43

标签: c# visual-studio debugging unhandled-exception

我的代码调用当前未运行的WCF服务。所以我们应该期待EndPointNotFoundException。 using语句尝试Close()导致CommunicationObjectFaultedException除外的故障连接Screen shot: Debugger breaking with Exception Unhandled popup。此异常在使用块周围的try catch块中捕获:

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");
        }
    }
}

注意服务EndPoint使用新的Guid,因此它永远不会有服务监听。

IDummyService是:

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

这会导致Visual Studio调试器(Visual Studio Professional 2017 15.4.1)与&#34; Exception Unhandled&#34;弹出: Stop visual studio from breaking on exception in Tasks 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按预期中断并使用&#34; Exception Thrown&#34;对话框而不是&#34; Exception Unhandled&#34;对话框。)

当我启用&#34;选项&#34; \&#34;调试&#34; \&#34;一般&#34; \&#34;启用我的代码&#34;调试器不会中断。但是,我有async个方法,其中异常应该留下我的代码,之后我await Task时会抓住异常。对于这些方法,我需要&#34;启用我的代码&#34;未选中;见Jack Zhai-MSFT

使用&#34;使用新的例外助手&#34;禁用(由Screenshot exception dialog when "Using the New Exception Helper" is disabled建议)Visual Studio仍然会中断并显示 https://bugs.eclipse.org/bugs/show_bug.cgi?id=515859 该对话框提供了一些其他信息:

  

异常在跨越托管/本机边界之前未被捕获。

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

是什么原因导致调试器错误地中断,以及如何使调试器既不会中断也不会处理CommunicationObjectFaultedException,也不会处理以后的处理程序async异常?

2 个答案:

答案 0 :(得分:2)

新的Exception功能在VS2017中,我们可以在TOOLS-&gt; OPTION-&gt; Debugging-&gt; General下禁用调试选项“Use the New Exception Helper”,它可以为您提供旧的Exception消息,您可以访问它

旧的Exception Message显示Exception跨越托管/本地边界: Screenshot exception dialog when "Using the New Exception Helper" is disabled

在TOOLS-&gt; OPTION-&gt; Debugging-&gt; General下检查“异常跨越AppDomain或托管/本机边界时中断”。禁用“当异常跨越AppDomain或托管/本地边界时中断”以避免Visual Studio破坏OP的情况(但要小心,因为这也会禁用在异常跨越AppDomain或托管/本机边界的其他情况下中断)。

答案 1 :(得分:1)

Close() - Faulted IClientChannel导致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;
        ...
    }
    ...
}

- (请参阅CommunicationObject.Close(TimeSpan) line #299中的.NET framework 4.7 reference source)。

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

设置组合(在TOOLS-&gt; OPTIONS-&gt; Debugger-&gt; General)中:

  • ☑例外跨越AppDomain或托管/本地边界时中断
  • ☐启用我的代码

导致Visual Studio中断显示:新的非模态异常弹出&#34;异常未处理&#34;: Screenshot: Visual Studio: Exception Unhandled (New Exception Handler)或模态对话框: Screenshot: Visual studio breaking on exception that crosses AppDomain or managed/native boundary

CommunicationObjectFaultedException以&#39; Not My Code&#39;开头;它跨越托管/非托管或AppDomain边界,同时仍然在“不是我的代码”中;最后输入我的代码&#39;它由catch - 块处理(但Visual Studio已经停止了此时的激励)。
由于例外是在“不是我的代码”中开始的。在越过边界时仍然存在,选择选项&#34;启用我的代码&#34;导致Visual Studio即使在跨越AppDomain或托管/非托管边界时也不会中断异常 当异常跨越AppDomain或托管/本地边界时,取消选择&#34;中断&#34;还会导致Visual Studio不会中断异常。

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