【问题标题】:Calling non-async methods inside async function [closed]在异步函数中调用非异步方法[关闭]
【发布时间】:2020-12-26 12:15:11
【问题描述】:

请帮我理解下面这段代码的异步/等待操作。

1. public async Task OuterMethodAsync(MyObject obj1)

2. {

3.     var dbResult = await repo.SomeDB_GetCallAsync(obj1.id);

4.     var httpResult = await Function1ContainingHTTPCallAsync(dbResult);

5.     dbResult.param1 = obj1.param1;

6.     var isSuccess = Function2(httpResult, dbResult);

7.     await repo.SomeDB_UpdateAsync(dbResult);

8.     if(isSuccess)
9.      {
10.         // Do some stuff
11.     }

12. }

Function2 应该返回 false,如果它的输入参数 httpResult 为空。

基于Function1ContainingHTTPCallAsync中的日志,

  1. 已经成功执行http调用,
  2. 返回了一个有效的响应httpResult,它是一个非空字符串

但是,根据Function2中的日志,

  1. 接收到输入参数httpResult为空
  2. 返回错误

这里,

  1. Function2 不是异步的
  2. Function1ContainingHTTPCallAsync异步
  3. SomeDB_GetCallAsync异步
  4. SomeDB_UpdateAsync异步
  5. OuterMethodAsync异步

我在这里看到的问题是 isSuccess 被设置为 false。另外,请注意,OuterMethod 有可能被多次调用(这是框架中针对失败的 HTTP 调用的重试机制)。考虑到 OuterMethod 本身就是作为 HTTP 调用调用的 API,是否会导致此问题?

【问题讨论】:

  • 这不会编译,因为OuterMethod 没有返回类型。请出示您的真实代码。
  • 第6行的一个参数是第4行的结果,所以第6行不能在第4行之前执行。
  • @SomeBody OuterMethod 返回 void(任务)
  • 此外,async 的任何内容都应以Async 为后缀。但是我的强迫症放在一边。 await 实际上正在等待,尽管其中一些代码可能会被推送到 IO 完成端口,但代码将按顺序运行。答案是,不,假设你 await 你所有的 async 调用,第 6 行将不会在第 4 行之前执行
  • 您的假设是否可能存在缺陷(仅当第 6 行在第 4 行之前执行时才会发生)?如果这个假设是正确的,Function2 将毫无用处,除非你依赖它的一些副作用。无论如何,是什么阻止你调试它并逐步查看会发生什么?

标签: c# async-await


【解决方案1】:

我在这里看到的问题是 isSuccess 被设置为 false,只有在第 6 行在第 4 行之前执行时才会发生这种情况。

你有正确的await 用法,所以:第6行没有在它应该执行之前执行。您将不得不研究Function2 可以返回false 的场景,也许使用调试器 来查看发生了什么。从这里我们可以看出,显示的代码很好。

请注意,在调试环境中,您可能能够看到 isSuccess 的值在它被有意义地定义/分配之前 - 例如,如果您在 @987654325 上放置一个断点@。这并不意味着第 6 行已经执行;它只是意味着调试器看到了幕后。严格来说,该值在第 6 行之前是未定义的,但实际上由于 C# 编译器发出了.locals init(至少目前是这样),它将是false,因为falsebool 的默认值。

您可能还想检查OuterMethod 是否可能被独立调用两次。

【讨论】:

  • 感谢您的详细回复。我还添加了几点: Function2 应该返回 false,只有当它的输入参数 httpResult 为 null 时。根据Function1ContainingHTTPCallAsync中的日志,它已经成功执行,并返回了一个有效的响应httpResult,它是一个非空字符串但是,基于中的日志i>Function2,它接收到输入参数 httpResult 为 null,因此返回 false
  • @CodingEveryDay 那么您需要查看Function1ContainingHTTPCallAsync 以查看在什么情况下它可以返回null - 也许有一个流氓catch (Exception ex) { Log(ex); return null; } - 因为编写的代码: 很好。或者,我再重复一遍:使用调试器,然后看看值是什么
  • 这发生在生产设置中,我在其中看到日志,当我在本地使用调试点尝试时,情况不一样。 Function2 实际上返回一个 true
  • @CodingEveryDay 那么你需要改进日志记录;无论发生什么:它并不特定于您显示的代码,因此您需要超越它
  • @CodingEveryDay 评论说我需要足够的代码来基本上重现它;你有密码,我没有;您必须对此进行调查
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-09
  • 1970-01-01
  • 2016-10-13
  • 2017-03-06
  • 1970-01-01
相关资源
最近更新 更多