我的代码调用当前未运行的WCF服务。所以我们应该期待EndPointNotFoundException
。 using语句尝试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");
}
}
}
注意服务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;禁用(由建议)Visual Studio仍然会中断并显示 https://bugs.eclipse.org/bugs/show_bug.cgi?id=515859 该对话框提供了一些其他信息:
异常在跨越托管/本机边界之前未被捕获。
我怀疑使用块可能会引入此托管/本地边界。
是什么原因导致调试器错误地中断,以及如何使调试器既不会中断也不会处理CommunicationObjectFaultedException
,也不会处理以后的处理程序async
异常?
答案 0 :(得分:2)
新的Exception功能在VS2017中,我们可以在TOOLS-&gt; OPTION-&gt; Debugging-&gt; General下禁用调试选项“Use the New Exception Helper”,它可以为您提供旧的Exception消息,您可以访问它
旧的Exception Message显示Exception跨越托管/本地边界:
在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()
返回的代理是通过RealProxy
(src)和RemotingServices.CreateTransparentProxy()
实现的,这些代理合并了托管代码和非托管代码,这可能会导致异常越过边界。
设置组合(在TOOLS-&gt; OPTIONS-&gt; Debugger-&gt; General)中:
导致Visual Studio中断显示:新的非模态异常弹出&#34;异常未处理&#34;: 或模态对话框:
CommunicationObjectFaultedException
以&#39; Not My Code&#39;开头;它跨越托管/非托管或AppDomain边界,同时仍然在“不是我的代码”中;最后输入我的代码&#39;它由catch
- 块处理(但Visual Studio已经停止了此时的激励)。
由于例外是在“不是我的代码”中开始的。在越过边界时仍然存在,选择选项&#34;启用我的代码&#34;导致Visual Studio即使在跨越AppDomain或托管/非托管边界时也不会中断异常
当异常跨越AppDomain或托管/本地边界时,取消选择&#34;中断&#34;还会导致Visual Studio不会中断异常。
using
- 阻止IClientChannel
,并在IClientChannel.State
之前检查Close()
。正如在What is the best workaround for the WCF client `using` block issue?