Search code examples
c#wcfexceptionasync-awaitfaultexception

Why is my WCF FaultException unhandled?


I have a service based on the following contract (abridged):

[ServiceContract]
public interface ISchedulerService
{
    [OperationContract]
    void Process(bool isForced);
}

The germane (IMHO) part of the implementation is:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, UseSynchronizationContext = false)]
public class SchedulerService : ISchedulerService
{
    public async void Process(bool isForced)
    {
        try
        {
            var prevStatus = Status;
            Status = SchedulerStatus.Processing;
            await ProcessListings();
            Status = prevStatus;
        }
        catch (Exception ex)
        {
            throw new FaultException(ex.Message);
        }
    }

    private static Task ProcessListings()
    {
        throw new Exception("ProcessListings failed.");           
        return Task.Delay(5000);
    }
}

The service is currently hosted in a tiny console app:

class Program
{
    private static readonly SchedulerService Scheduler = SchedulerService.Instance;
    private static ServiceHost schedulerHost;

    protected static void OnStart()
    {
        try
        {
            if (schedulerHost != null)
            {
                schedulerHost.Close();
                schedulerHost = null;
            }
            schedulerHost = new ServiceHost(Scheduler);
            schedulerHost.Open();
            Scheduler.Start();
        }
        catch (Exception ex)
        {
            //EventLog.WriteEntry("Exception: " + ex.Message);
            throw;
        }
    }
}

And, finally, the client:

private readonly SchedulerServiceClient _proxy= new SchedulerServiceClient();
...
void ExecuteProcessNowCommand()
{
    try
    {
        _proxy.Process(true);
    }
    catch (Exception ex)
    {
        if (exception is SchedulerException)
        {
            MessageBoxFacility.ProcessingError((SchedulerException)exception);
        }
    }
}

where SchedulerServiceClient is the proxy that is generated when I add a service reference. Up until now, I have successfully hosted the WCF inside a live Windows Service and tested non-exception functionality. Everything was fine until I added exception handling. I know this is a complex scenario, but most examples I have seen suggest that the FaultException would at least be caught by the general Exception handler in the client. My debugger makes me guess the exception doesn't even make it to the proxy, and it remains unhandled in the MVC code. When I hit 'continue' enough, I end up at a screen telling me the stack contains only external code. This is the stack trace for that external code:

at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__1(Object state)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</ExceptionString></Exception></TraceRecord>

This makes me think my use of async in the MCV service might me playing a role, but then maybe it's only an innocent middleman. Please help me try and determine why the exception is not even propagated to the client.


Solution

  • Exceptions in async methods are stored in the returned task. async void methods don't return a task and so the exception is thrown on a ThreadPool thread tearing down the AppDomain.

    Don't use async void anywhere other than event handlers.

    If you return a task you can await that task and the exception will be rethrown.