【问题标题】:Why is my WCF FaultException unhandled?为什么我的 WCF FaultException 未处理?
【发布时间】:2015-03-06 14:48:03
【问题描述】:

我有一项基于以下合同的服务(删节):

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

实施的密切相关(恕我直言)部分是:

[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);
    }
}

该服务目前托管在一个小型控制台应用程序中:

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;
        }
    }
}

最后是客户:

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

其中SchedulerServiceClient 是我添加服务引用时生成的代理。到目前为止,我已经成功地将 WCF 托管在实时 Windows 服务中并测试了非异常功能。一切都很好,直到我添加了异常处理。我知道这是一个复杂的场景,但我看到的大多数示例表明 FaultException 至少会被客户端中的一般 Exception 处理程序捕获。我的调试器让我猜想这个异常甚至没有进入代理,并且它在 MVC 代码中仍未处理。当我点击“继续”足够多时,我最终会出现一个屏幕,告诉我堆栈只包含外部代码。这是该外部代码的堆栈跟踪:

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>

这让我觉得我在 MCV 服务中使用 async 可能是我扮演了一个角色,但也许它只是一个无辜的中间人。请帮助我尝试确定为什么异常甚至没有传播到客户端。

【问题讨论】:

    标签: c# wcf exception-handling async-await faultexception


    【解决方案1】:

    async 方法中的异常存储在返回的任务中。 async void 方法不返回任务,因此在 ThreadPool 线程上引发异常,从而拆除 AppDomain

    不要在除事件处理程序之外的任何地方使用async void

    如果你返回一个任务,你可以await那个任务,异常会被重新抛出。

    【讨论】:

    • 异常被等待异步方法的方法正确捕获,即Process确实捕获了ProcessListings抛出的异常。 AppDomain 看起来仍然很好,而 Process 抛出它捕获的异常。
    • @ProfK ProcessListings 不是async 方法。它只是返回一个任务。 Processasync 方法抛出的异常,没有被捕获。
    • 啊哈,谢谢!我刚刚删除了所有异步,异常到达了客户端。那么,我现在是否应该在 Process 中创建任务,并在代理中 await 生成异步方法?
    • @ProfK 差不多。不要创建任务,只需更改返回值,编译器就会为您生成。您可以查看此以获取更多信息:codeproject.com/Articles/613678/…
    • 谢谢。我开始了又一次漫长的学习攀登。我仍然接近混合 WPF、计时器、WCF 和 Windows 服务的那一种。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    相关资源
    最近更新 更多