我的代码调用了一个当前未运行的WCF服务。因此,我们应该期望出现EndPointNotFoundException
异常。使用语句尝试Close()
故障连接,导致了一个CommunicationObjectFaultedException
异常。这个异常被包含在一个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");
}
}
}
请注意,服务端点使用新的Guid,因此它永远不会有服务在监听。
IDummyService
是:
[ServiceContract]
interface IDummyService
{
[OperationContract]
string Echo(string e);
}
这会导致Visual Studio调试器(Visual Studio Professional 2017 15.4.1)出现“异常未处理”弹窗: 在代码中已经捕获了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 会弹出“异常抛出”对话框而非“未处理异常”对话框)。
当我启用“选项”\“调试”\“常规”\“启用我的代码”时,调试器不会停止。但是,我有一些带有 async
方法的代码,其中异常应该离开我的代码,并在 await
Task
时才捕获异常。对于这些方法,我需要取消勾选“启用我的代码”,请参见Stop visual studio from breaking on exception in Tasks。
即使已禁用“使用新的异常助手”(如Jack Zhai-MSFT所建议),Visual Studio 仍会停止并显示以下内容: 此对话框提供了一些额外的信息:
异常在跨越 托管/本机 边界之前未被捕获。
我怀疑使用块可能会引入此托管/本机边界。
是什么导致了调试器的误报,如何使调试器既不在处理 CommunicationObjectFaultedException
时停止,也不在后续处理 async
异常时停止?