【问题标题】:Converting synchronous WCF service client calls to asynchronous将同步 WCF 服务客户端调用转换为异步
【发布时间】:2013-09-18 20:19:24
【问题描述】:

我正在学习线程、任务和异步编码,并尝试将这些概念应用到我每天工作的 Web 窗体应用程序中。

到目前为止我有:

  • 配置的服务参考如下:

  • 更改的客户端调用来自

    MyServiceClient msc = new MyServiceClient();
    try
    {
         myData =  msc.GetData();                    
         msc.Close();
    }
    catch (Exception)
    {
         msc.Abort();
         throw;
    }
    

    MyServiceClient msc = new MyServiceClient();
    try
    {
         myData =  msc.GetDataAsync().Result;                    
         msc.Close();
    }
    catch (Exception)
    {
         msc.Abort();
         throw;
    }

我直接调用结果以在任务上隐式调用 .Wait() 并保持代码基本不变。

  1. 在执行 I/O 的同时释放应用程序池中的线程用于其他工作是否正确?
  2. 我需要以不同的方式处理异常吗?
  3. Close() 和 Abort() 是否仍然必要且相关?

【问题讨论】:

  • msc.GetDataAsync().Result;msc.GetData(); 相同。不作为await msc.GetDataAsync();使用的Tasks是什么@
  • @I4V msc.GetDataAsync().Result;msc.GetData(); 不同。前者涉及两个线程后者只涉及一个。
  • @I4V 我不打算并行处理多个服务调用,我的目的是为其他工作释放线程。如果我使用await,那么我需要将堆栈中的每个方法标记为async,这需要更多的工作。我可能会在走路之前尝试跑步,但这是我目前的理解。
  • @SriramSakthivel 当然它们不一样,我只是想说调用者线程将体验到的效果是一样的。 (BTW:Former理论上不需要涉及两个线程)
  • @mizzle 双向阻塞调用线程。我仍然没有看到使用asynMethod.Result 的优势

标签: c# wcf asynchronous


【解决方案1】:

我直接调用结果以在任务上隐式调用 .Wait() 并保持代码基本不变。

我完全不推荐这个。在一般情况下,calling Result or Wait in async code can cause deadlocks(正如我在博客中解释的那样)。由于svcutil 实现这些方法的方式,它可能(当前)有效,但我不建议练习编写这样的代码。

async 通过代码库增长会更好:

MyServiceClient msc = new MyServiceClient();
try
{
     myData = await msc.GetDataAsync();                    
     msc.Close();
}
catch (Exception)
{
     msc.Abort();
     throw;
}
  1. 在执行 I/O 的同时释放应用程序池中的线程用于其他工作是否正确?

没有。你在做什么真的没有意义。您根本不允许调用是异步的。

如果您使用await,那么是的,您确实获得了异步操作的好处(即释放 UI 线程)。

  1. 我需要以不同的方式处理异常吗?

如果您使用的是await,那么不,您现有的代码可以正常工作。如果您使用的是Result,那么是的,您的所有异常都将包含在AggregateException 中。

  1. Close() 和 Abort() 是否仍然必要且相关?

是的。

【讨论】:

  • 迄今为止最全面的答案。如果我在呈现页面之前需要这些数据,因此需要等待它完成,那么使用异步调用似乎没有任何好处。如果在呈现页面之前我有多个服务方法要调用,那么在堆栈上使用asyncawait 或使用任务数组和WaitAll() 并使用同步方法有什么好处吗?
  • @mizzle:实际上,我建议首先重新考虑您的页面 UI。如果页面依赖于加载数据,则具有将立即显示的“正在加载”状态,并在加载完成时让异步数据加载将该页面更新为“正常”状态。这需要更多的工作,但您会得到一个完全响应的 UI(例如,即使网络中断,您的应用也不会死机)。
【解决方案2】:

如果调用异步版本并等待完成比正常方式更好,框架可以为您透明地执行此操作。它不这样做的事实表明,这种方法并不好。

如果我使用 await,则需要将堆栈中的每个方法标记为异步,这需要更多工作。

就是这样。您必须更改整个调用堆栈,因为您的线程必须在 IO 运行时将控制权返回给线程池。您必须退出堆栈上的 all 函数。感谢上帝 async/await 使这主要是一种机械练习。

因此,您应该使用 async/await 以响应您无法获得的性能需求。默认情况下不要使用它。首先确定,你现在是否真的有太多的线程。如果不是,您很可能根本不需要异步。把时间花在别处。

【讨论】:

    猜你喜欢
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多