【问题标题】:ASP.NET MVC 5 and WCF async troublesASP.NET MVC 5 和 WCF 异步问题
【发布时间】:2018-11-26 06:04:02
【问题描述】:

我们的应用程序使用 WCF 作为数据提供者,并且在某些页面上,我们对不同的服务进行了多次调用。我认为优化的好作品,并开始将其重写为async。所以在重写之前它看起来像

public ActionResult SomeAction(int id)
{
var r1 = AService.Call1();
var r2 = BService.Call2();
var r3 = CService.Call3();
//another logic
}

现在变成了

public async Task<ActionResult> SomeAction(int id)
{
var r1 = await AService.Call1Async();
var r2 = await BService.Call2Async();
var r3 = await CService.Call3Async();
//another logic
}

使用这种方法我遇到了两个问题:

  1. 在第一次服务调用应用程序陷入无休止的加载和 没有执行其他操作。调试显示相同 - 第一次调用和 之后什么都没有。
  2. 我们的一些类不能使用异步方法,a.e.我们的静态 AuthorizationProvider。

更新: @zuckerberg 回答有助于优化(我正在创建任务并将它们放入等待的 Task.WhenAll()),但我仍然在 WCF 服务上挂起——而同步调用正常, 异步调用将调用逻辑转入睡眠状态并且永远不会唤醒它。

【问题讨论】:

  • 你是否屏蔽了CallAsync中的任何一个。
  • 您对 async/await 的适应看起来不错。所以肯定有其他东西在起作用,但这里没有人可以查看您的 PC。所以开始设置minimal reproducible example

标签: c# asp.net-mvc wcf async-await


【解决方案1】:

使用 async/await 它们异步运行。这意味着他们不会等待对方或主线程。如果存在依赖关系,或者您需要在返回结果之前先等待所有 3 个完成,那么我建议使用类似的东西:

var r1 = await AService.Call1Async();
var r2 = await BService.Call2Async();
var r3 = await CService.Call3Async();

await Task.WhenAll(r1, r2, r3);
//more logic

希望这有助于将您推向正确的方向。但是,如果没有看到更多代码,我无法判断仅通过异步/等待您的调用是否真的会提高性能(它并不总是性能提升器)并且您的时间/精力可能会更好地花在其他地方。

祝你好运!

【讨论】:

  • 有点帮助,所以谢谢你。需要更多研究,尤其是关于我们 AuthorizationProvider 中的挂起和使用。
  • 你的答案是错误的,该代码永远不会编译,除非CallAsync 返回Tasl&lt;Task&gt;
  • 你不能等待两次。但此外,问题中的异步调用按顺序执行。你的假设是错误的。
  • @PauloMorgado 实际上,我从 SO 上接受的答案中复制并修改了一个示例,并将其调整为 OP 的示例。我没有编写可以编译的代码。是为了解释。我还提到,如果没有更多代码,我不能肯定地说。我试图给他们正确的想法,而不是代码。总是更容易评论和推翻别人的尝试,发布你自己的答案怎么样。
  • @bommelding 就像我说的那样,这完全取决于 OP 在做什么,并且给出的代码对于“更多逻辑”作为评论并没有太大帮助。我不得不假设他们正在做的 await 不是方法异步的一部分,这意味着具有“更多逻辑”的部分可能是主线程的 return await thing 。您确实可以在一个方法中等待任意多次。但是,如果您知道答案,我希望您发布一个以便我们查看?
【解决方案2】:

1. 使用静态类的构造函数的内部异步调用启动函数是个坏主意,但SomeMethodAsync().Result 有帮助——当然控制器没有任何好处,但在这种小情况下它是可以接受的。

2.是的,我误解了async/await,所以我将代码重写为这样的:

var get1Task = AService.Call1Async();
var get2Task = BService.Call2Async();
var get3Task = CService.Call3Async();

await Task.WhenAll(get1Task, get2Task, get3Task);
var r1 = get1Task.Result;
var r2 = get2Task.Result;
var r3 = get3Task.Result;
//more logic

它让我在有很多 WCF 调用的页面上得到了很好的加速,我很高兴。

感谢@zuckerberg 指出了正确的方向。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2014-07-10
    • 2015-06-10
    • 2018-07-11
    • 2017-03-31
    相关资源
    最近更新 更多