一般问题
我刚刚发现了一个奇怪的行为,因为在方法的签名中缺少 async
修饰符。有了它,我得到了预期的行为,但没有它,我的程序就会表现得很奇怪。
问题是,该方法的主体是完全同步的:看不到单个 await
。我什至(如预期的那样)在 1998 年收到编译器警告:
那么诱惑就是将其移除。 (我的意思是,编译器基本上是告诉我这样做的!)当我删除它时,我开始可靠地获得意外行为。
我的问题是: 在没有 await 时 async 真正在做什么?
上下文/细节
我不认为我的应用程序的细节与我渴望理解的基本解释相关,但我将它包含在这里以提供一些 flavor ......
我正在开发的程序使用来自服务总线的消息。我的方法的签名是:
public async Task<BrokeredMessage> ProcessMessageAsync(BrokeredMessage inMessage)
历史背景:我最初从同事编写的一个类似程序中借用了这个,方法名称(暗示异步操作)是接口(interface)实现的一部分。
当我删除
async
修饰符时,我遇到的奇怪行为是方法的主体已执行,但消息返回为无法传递。这样做的一个有趣结果是,每次重试尝试都会处理消息。 (我很幸运这是一个低数字!)更新
正如 Skeet 先生所指出的,重要的是,尽管签名 promise 返回
Task
类型的值,但我的方法实际上返回 null
。 最佳答案
在可观察行为方面:
Task
在实现方面,编译器将生成一个状态机来处理所有异步性。但这不应该改变任何其他行为。
我无法立即想到您会看到此消息行为的任何原因,除非由于处理异常而有所不同。如果调用代码正在捕获异常但忽略了错误的任务(反之亦然),这肯定可以解释差异。我的第一个诊断步骤是添加一些日志记录以查看该方法是否成功完成或是否在某处抛出异常。
现在您已经声明要返回
null
,从调用者的角度来看,这是一个明显的区别:返回 null
的 Task<BrokeredMessage>
值的方法与返回 Task<BrokeredMessage>
的 null
值及其 ojit_code 属性之间存在巨大差异。也许调用者正在取消引用返回的值,并且正在抛出 Result
?如果是这种情况,您的第一个停靠点应该是找出您之前无法看到该异常的原因 - 这表明缺少一些日志记录。然后你可以通过改变它来修复它:
return null;
至
return Task.FromResult<BrokeredMesage>(null);
关于c# - 在签名中包含 async(在 body 中没有 await)对程序流程有什么影响?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41593735/