My code calls a WCF service that is current not running. So we should expect the EndPointNotFoundException
. The using statement tries to Close()
the faulted connection which causes a CommunicationObjectFaultedException
which is excepted. This exception is caught in a try catch block surrounding the using block:
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");
}
}
}
Note the service EndPoint uses a fresh Guid so it will never have a service listening.
IDummyService
is:
[ServiceContract]
interface IDummyService
{
[OperationContract]
string Echo(string e);
}
This causes the Visual Studio debugger (Visual Studio Professional 2017 15.4.1) to break with an "Exception Unhandled" popup:
The exception on which Visual Studio breaks is System.ServiceModel.CommunicationObjectFaultedException
which is caught in the code.
Stepping to continue execution shows that catch(CommunicationObjectFaultedException ex)
is reached. Using LinqPad to run the demo also shows that the exception is caught as expected.
I also tried explicitly (double) closing the channel instead of using the 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");
}
}
}
This still causes the debugger to break on the Close
statement.
My Exception Settings has System.ServiceModel.CommunicationObjectFaultedException
unchecked. (When it is checked Visual studio breaks as expected and with the "Exception Thrown" dialog instead of the "Exception Unhandled" dialog).
When I enable "Options"\"Debugging"\"General"\"Enable Just My Code" the debugger does not break. However, I have async
methods where the exception should leave my code and I later catch the exception when await
ing the Task
. For these methods I need "Enable Just My Code" unchecked; see Stop visual studio from breaking on exception in Tasks.
With "Using the New Exception Helper" disabled (as suggested by Jack Zhai-MSFT) Visual Studio still breaks and it shows The dialog provides some additional information:
The exception is not caught before it crosses a managed/native boundary.
I suspect that the using block probably introduces this managed/native boundary.
What causes the debugger to break by mistake and how to make the debugger not break neither or handled CommunicationObjectFaultedException
s nor on later handler async
exceptions?
The new Exception feature was in VS2017, we could disable debugging option "Use the New Exception Helper" under TOOLS->OPTION->Debugging->General which could provide you the old Exception messages, you could visit it.
The old Exception Message shows that the Exception crosses a managed/native boundary:
Check "Break when Exceptions cross AppDomain or managed/native boundaries" under TOOLS->OPTION->Debugging->General. Disable "Break when Exceptions cross AppDomain or managed/native boundaries" to avoid Visual Studio breaking on the OP's situation (be careful though since this also disables breaking on other situations where an exception crosses an AppDomain or managed/native boundary).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With