Kas*_*erg 5 c# debugging unhandled-exception visual-studio
我的代码调用了当前未运行的WCF服务。所以我们应该期待EndPointNotFoundException。using语句尝试对Close()导致a的异常连接进行故障处理CommunicationObjectFaultedException。在use块周围的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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
注意,服务EndPoint使用新的Guid,因此它将永远不会监听服务。
IDummyService 是:
[ServiceContract]
interface IDummyService
{
[OperationContract]
string Echo(string e);
}
Run Code Online (Sandbox Code Playgroud)
这会导致Visual Studio调试器(Visual Studio Professional 2017 15.4.1)中断并显示“未处理的异常”弹出窗口:
唯一的例外上的Visual Studio破裂是System.ServiceModel.CommunicationObjectFaultedException其被抓的代码。
步进继续执行表明catch(CommunicationObjectFaultedException ex)已达到。使用LinqPad运行演示还显示异常已按预期捕获。
我还尝试了显式(两次)关闭通道,而不是使用using-block:
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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
这仍然会导致调试器在该Close语句上中断。
我的例外设置System.ServiceModel.CommunicationObjectFaultedException未选中。(选中该选项后,Visual Studio会按预期中断,并显示“抛出异常”对话框而不是“未处理异常”对话框)。
当我启用“选项” \“调试” \“常规” \“仅启用我的代码”时,调试器不会中断。不过,我有async方法在异常应该离开我的代码,当我后来捕获异常await荷兰国际集团的Task。对于这些方法,我需要未选中“启用我的代码”;请参阅在Tasks中阻止Visual Studio打破异常。
禁用“使用新异常助手”(如Jack Zhai-MSFT的建议),Visual Studio仍会中断,并且显示
该对话框提供了一些其他信息:
在跨越托管/本机边界之前不会捕获到该异常。
我怀疑using块可能会引入此托管/本地边界。
是什么原因导致调试器错误地中断,以及如何使调试器既不中断也不处理,CommunicationObjectFaultedException也不会在以后的处理程序async异常时中断?
Close()-ing a会导致 a :Faulted IClientChannelCommunicationObjectFaultedException
\n\n\nRun Code Online (Sandbox Code Playgroud)\npublic void Close(TimeSpan timeout)\n{\n ...\n switch (originalState)\n {\n case CommunicationState.Created:\n case CommunicationState.Opening:\n case CommunicationState.Faulted:\n this.Abort();\n if (originalState == CommunicationState.Faulted)\n {\n throw TraceUtility.ThrowHelperError(this.CreateFaultedException(), Guid.Empty, this);\n }\n break;\n ...\n }\n ...\n}\n
--(请参阅.NET Framework 4.7 参考源中的CommunicationObject.Close(TimeSpan) 第 299 行)。
\n\n-blockusing被转换为try { ... } finally { Dispose(); }并在该块离开时Dispose()调用。Close()返回的代理CreateChannel()是通过RealProxy(src)实现的,RemotingServices.CreateTransparentProxy()这些代理结合了托管和非托管代码,这可能会导致跨越边界的异常。
设置组合(在“工具”->“选项”->“调试器”->“常规”中):
\n\n导致 Visual Studio 中断显示:新的非模式异常弹出窗口“Exception Unhandled”:\n
或模式对话框:\n
开头CommunicationObjectFaultedException为“不是我的代码”;它跨越托管/非托管或 AppDomain 边界,同时仍处于“不是我的代码”中;最后进入“我的代码”,由 -block 处理catch(但此时 Visual Studio 已经停止执行)。
\n由于异常从“不是我的代码”开始,并在跨越边界时保留在那里,因此选择“仅启用我的代码”选项会导致 Visual Studio 不会因异常而中断,即使它跨越 AppDomain 或托管/非托管边界。
\n取消选择“异常跨越 AppDomain 或托管/本机边界时中断”也会导致 Visual Studio 不会在异常时中断。
using并在 -ing之前IClientChannel进行检查。正如WCF 客户端“using”块问题的最佳解决方法是什么?中所做的那样IClientChannel.StateClose()