C# Visual studio在使用“未处理的异常”对话框处理异常时中断
我的代码调用当前未运行的WCF服务。因此,我们应该期待未来。using语句尝试删除导致异常的错误连接。在使用块周围的try-catch块中捕获此异常:C# Visual studio在使用“未处理的异常”对话框处理异常时中断,c#,visual-studio,debugging,unhandled-exception,C#,Visual Studio,Debugging,Unhandled Exception,我的代码调用当前未运行的WCF服务。因此,我们应该期待未来。using语句尝试删除导致异常的错误连接。在使用块周围的try-catch块中捕获此异常: class Program { static void Main() { try { using (ChannelFactory<IDummyService> unexistingSvc = new ChannelFactory<IDummyService&
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");
}
}
}
这会导致Visual Studio调试器(Visual Studio Professional 2017 15.4.1)中断,并出现“异常未处理”弹出窗口:
Visual Studio中断的异常是System.ServiceModel.CommunicationObjectFaultedException
,它被捕获在代码中
单步执行以继续执行显示已到达捕获(CommunicationObjectFaultedException ex)。使用LinqPad运行演示还表明异常是按预期捕获的
我还尝试显式(双重)关闭通道,而不是使用的块:
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");
}
}
}
类程序
{
静态void Main()
{
尝试
{
使用(ChannelFactory unexistingSvc=newchannelfactory(new NetNamedPipeBinding(),“net。pipe://localhost/UnexistingService-“+Guid.NewGuid().ToString()))
{
IDummyService chan=null;
尝试
{
chan=unexistingSvc.CreateChannel();
chan.Echo(“你好”);
}
捕获(EndpointNotFoundException ex)
{
WriteLine($“应为:{ex.Message}”);
}
最后
{
尝试
{
(chan作为IClientChannel)?.Close();
}
捕获(通信对象故障异常异常)
{
WriteLine($”由Close:{ex.Message}引起);
}
}
}
}
捕获(EndpointNotFoundException ex)
{
Console.WriteLine(“预期”);
}
捕获(通信对象故障异常异常)
{
WriteLine(“预期:由关闭引发EndPointNotFoundException的通道引起”);
}
}
}
这仍然会导致调试器在Close
语句上中断
我的异常设置未选中System.ServiceModel.CommunicationObjectFaultedException
。(选中该选项后,Visual studio将按预期中断,并使用“异常引发”对话框而不是“异常未处理”对话框)
当我启用“选项”\“调试”\“常规”\“仅启用我的代码”时,调试器不会中断。但是,我有async
方法,其中异常应该离开我的代码,然后在等待任务时捕获异常。对于这些方法,我需要取消选中“仅启用我的代码”;看
禁用“使用新异常帮助器”(如建议的)后,VisualStudio仍会中断并显示
该对话框提供了一些附加信息:
异常在跨越托管/本机边界之前不会被捕获
我怀疑using块可能引入了这个托管/本机边界
是什么原因导致调试器错误地中断,以及如何使调试器既不中断也不中断或处理CommunicationObjectFaultedException
s,也不中断后续处理程序async
异常?新的异常功能在VS2017中,我们可以禁用调试选项“使用新的异常帮助程序”在工具->选项->调试->常规下,您可以访问它,该工具可以为您提供旧的异常消息
旧异常消息显示异常跨越托管/本机边界:
选中“工具->选项->调试->常规”下的“异常跨越AppDomain或托管/本机边界时中断”。禁用“异常跨越AppDomain或托管/本机边界时中断”以避免Visual Studio在OP的情况下中断(但要小心,因为这也会在异常跨越AppDomain或托管/本机边界的其他情况下禁用中断)。-ing a会导致:
--(见中的)
using
-块被转换为try{…}finally{Dispose();}
,并在块离开时调用。由返回的代理通过()实现,这些代理将托管代码和非托管代码结合起来,这可能会导致异常跨越边界
设置组合(在工具->选项->调试器->常规中):
- ☑ 异常跨越AppDomain或托管/本机边界时中断
- ☐ 仅启用我的代码
导致Visual Studio中断显示:新的非模式异常弹出窗口“异常未处理”:
或模式对话框:
以“非我的代码”开头;它跨越托管/非托管或AppDomain边界,但仍处于“非我的代码”状态;最后输入“我的代码”,由catch
-块处理(但Visual Studio此时已停止执行)。
由于异常从“非我的代码”开始,并在跨越边界时保持不变,因此选择“仅启用我的代码”选项会导致Visual studio即使跨越AppDomain或托管/非托管边界也不会中断异常。
取消选择“异常跨越AppDomain或托管/本机边界时中断”也会导致Visual Studio在异常时不中断
这提供了两种解决方案/变通方法
- 选择“异常跨越AppDomain或托管/本机边界时中断”和“仅启用我的代码”的不同组合
- 请勿使用<代码>使用<代码>-块进行检查。正如在
如果在VS2017中禁用“工具->选项->调试->常规”下的调试选项“使用新异常帮助器”,那么
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");
}
}
}
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;
...
}
...
}