【问题标题】:WCF ASync ...Lost Exception at Client SideWCF ASync ...在客户端丢失异常
【发布时间】:2013-10-10 11:19:50
【问题描述】:

我尝试学习 WCF,所以我玩了一个简单的 WCF 应用程序,From Source Stephen Cleary => async-wcf-today-and-tomorrow

代码片段如下:

简单合约:

[DataContract]
public class CalculatorFault
{
  [DataMember]
  public string Message { get; set; }
}

[ServiceContract]
public interface ICalculator
{

  [OperationContract]
  [FaultContract(typeof(CalculatorFault))]
  Task<uint> DivideAsync(uint numerator, uint denominator);
}

简单的服务实现:

public class Calculator : ICalculator
{
  public async Task<uint> DivideAsync(uint numerator, uint denominator)
  {
    try
    {
      var myTask = Task.Factory.StartNew(() => numerator / denominator);
      var result = await myTask;
      return result;
    }
    catch (DivideByZeroException)
    {
      throw new FaultException<CalculatorFault>(new CalculatorFault { Message = "Undefined result" });
    }
  }
}

以及来自客户的简单调用:

static class Program
{
  static async Task CallCalculator()
  {
    try
    {
      var proxy = new CalculatorClient();
      var task = proxy.DivideAsync(10, 0);
      var result = await task;
      Console.WriteLine("Result: " + result);
    }
    catch (FaultException<CalculatorFault> ex)
    {
      Console.Error.WriteLine("Error: " + ex.Detail.Message);
    }
  }

  static void Main(string[] args)
  {
    try
    {
      CallCalculator().Wait();
    }
    catch (Exception ex)
    {
      Console.Error.WriteLine(ex);
    }

    Console.ReadKey();
  }
}

它有效:当我尝试将一个数字除以零时,我得到了来自客户端的异常。

但我想做的是将 WCF 调用委托给其他函数,例如旧的回调函数。所以我在客户端尝试以下操作

async Task CallCalculator()
{
    try
    {
         var task = channel.DivideAsync(10, 0);
         task.ContinueWith(OnWorkCompleted); 
    }
   catch (FaultException<CalculatorFault> ex)
    {
        Console.Error.WriteLine("Error: " + ex.Detail.Message);
    }

}

void OnWorkCompleted(Task<uint> task)
{      
     var result = task.Result;
    Console.WriteLine("Result From Async: " + result);
}

这也有效,但是当我尝试除以零时,我没有收到异常,尽管服务抛出异常,但客户端没有结果。

为什么会发生这种情况?如何修复它以从客户端捕获异常?

【问题讨论】:

    标签: wcf c#-4.0 task-parallel-library


    【解决方案1】:

    作为一般规则,不要在async 代码中使用ContinueWith;你应该改用await

    当您调用task.Result 时,您的代码实际上发生了异常,但CallCalculator 中的catch 块无法捕获此异常。

    所以,我会这样做:

    async Task CallCalculator()
    {
      try
      {
         var result = await channel.DivideAsync(10, 0);
         OnWorkCompleted(result); 
      }
     catch (FaultException<CalculatorFault> ex)
      {
        Console.Error.WriteLine("Error: " + ex.Detail.Message);
      }
    }
    

    【讨论】:

    • .net 4 用户如果不能使用 await 怎么办?
    • @OvidiuBuligan:我推荐 Microsoft.Bcl.Async 用于除 ASP.NET 之外的所有 .NET 4.0 方案。
    • 很抱歉提出另一个稍微相关的问题。如果您想为目标框架设置为 .net 4 的项目创建代理,“基于异步生成任务”将灰显。我通过在 .net 4.5 上生成基于异步的任务并使用一些 bat 脚本切换回 4.0 以从生成的 xml 中删除一行来欺骗它。据我所知,它的工作原理。您知道为什么当项目目标运行时为 4.0 时他们将该选项设为灰色吗? (我在桌面使用 vs 2013 express)
    • .NET 4.0 没有内置 async 支持(它需要包)。你可以按照你描述的方式或wrap the APM methods from the .NET 4.0-based proxy.
    猜你喜欢
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 2014-10-19
    • 2011-07-01
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多