【问题标题】:Error handling using delegates使用委托处理错误
【发布时间】:2015-03-05 17:39:25
【问题描述】:

我有一个常用的方法来处理可能从多个函数返回的特定错误:

protected async Task<T> RunMyMethod<T>(Func<T> method)
{
    try
    {
        var returnValue = await Task.Run<T>(method);
        return returnValue;
    }
    catch (MyCustomException)
    {
        // Force a clean shutdown of the software 
        ShutdownApplication();
        return default(T);
    }
}

这是一个如何在派生类中使用它的示例:

private async Task<IEnumerable<MyData>> GetMyData()
{
    var returnValue = await base.RunMyMethod<IEnumerable<MyData>>(() =>
    {
        var returnval = GetMyDataFromServer();
        return returnval;
    });

    return returnValue;
}

MyCustomException 类型的异常发生在GetMyDataFromServer() 中时,软件不会进入catch 块。我在函数GetMyData() 中收到以下错误:

An exception of type 'System.ServiceModel.FaultException`1' occurred in mscorlib.dll but was not handled in user code

Additional information: Exception of type 'MyCustomException' was thrown.

这是仅启用了用户未处理的异常。

GetMyDataFromServer() 与 WCF 服务通信。该服务是引发错误的原因。

ChannelFactory<TChannel> cf = new ChannelFactory<TChannel>(endPointName);
Binding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);                    

var clientCredentials = new ClientCredentials();

. . .

channel = cf.CreateChannel();
var data = channel.CallWCFService();

在网上看了一圈,看来处理这个问题的正确方法是改变基本方法如下:

protected async Task<T> RunMyMethod<T>(Func<T> method)
{
    var returnValue = await Task.Run<T>(method).ContinueWith(e => 
    {                     
        ShutdownApplication();
        return default(T);
    }, TaskContinuationOptions.OnlyOnFaulted);

    return returnValue;
}

当我运行这个时,我显然没有捕捉到正确的错误消息,但我只是得到一个TaskCancellationException

所以,我有两个问题:我关于如何处理此异常的结论是否正确,如果是,我如何捕获特定错误;为什么我会收到TaskCancellationException

【问题讨论】:

  • RunMyMethod 版本 1 中的代码应该可以按预期工作。我的意思是如果GetMyDataFromServer 抛出MyCustomException,它应该捕获MyCustomException 并调用ShutdownApplication。你能展示GetMyDataFromServer的实现吗?或者你可以发一个short but complete sample 吗?
  • 你能添加GetMyDataFromServer的代码吗?
  • 就本期而言,GetMyDataFromServer() 只是一个抛出新的MyCustomException 的函数
  • @pm_2 在这种情况下RunMyMethod 会抓住它。
  • 我已经更新了问题;虽然它似乎没有

标签: c# error-handling task-parallel-library async-await task


【解决方案1】:

您会得到TaskCancellationException,因为延续被取消,因为它是有条件的(即TaskContinuationOptions.OnlyOnFaulted),并且由于先前的任务没有出错,因此条件不满足。

没有理由使用这种添加延续的方法。像一开始那样使用async-await 就足够了(甚至更简单)。

问题是您正在尝试捕获 MyCustomException 但这不是抛出的异常。由于您使用的是 WCF,因此例外是 FaultException。您可以检查存储在FaultException.InnerException 中的“真实”异常。

【讨论】:

  • 我已经更新了问题。 GetMyDataFromServer 中没有错误处理。异常没有被 catch 块捕获
  • @pm_2 在GetMyDataFromServer 中存在未被您的代码捕获的未处理异常的唯一方法是您在不同线程上以该方法运行代码。这就是我们要求您展示代码的原因。
  • 我已经用一些额外的信息更新了这个问题。我不相信错误是在不同的线程中引发的(尽管它最初确实来自 WCF 服务)。
  • @pm_2 例外不是MyCustomException。看看我的更新。
  • FaultException.InnerExcetion 为空。但是,您是对的 - 这就是我没有发现错误的原因。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多