Zol*_*ály -1 c# warnings asynchronous
这不是一个调试类型的问题,我只是在asycnchronous编程领域寻找一个特定的教育,一个我不可否认的领域,在这里.
我正在编写一个程序,我需要它来定期拨打电话,同时还要执行其他功能.我查找了如何编写一个异步方法来实现这一点,并实际上让它工作.
令我困惑的是,当我从我的Main方法调用它时,我得到一个警告,说我应该使用await关键字让程序等待方法调用完成,否则我可能无法得到预期的行为,这是对我很奇怪.我认为,编写异步方法的关键在于让它运行,然后继续前进而不等待它完成,因此注意警告会破坏目的.另一方面,我并不傲慢地认为我比开发Visual Studio的专业人员更了解并添加了警告,因此必须有更多情况下添加await关键字更有意义.
我的问题是:通常使用的异步方法如何保证听到此警告?
编辑:人员请求代码和警告的特定文本,因此:
异步方法:
public static async Task FindPairs(TimeSpan interval, CancellationToken cancellationToken)
{
while (true)
{
lock (relevantVariable)
{
doStuffEveryInterval();
}
await Task.Delay(interval, cancellationToken);
}
}
Run Code Online (Sandbox Code Playgroud)
并且警告是这样的:"因为没有等待这个调用,所以当前方法的执行在调用完成之前继续.考虑将'await'运算符应用于调用的结果.当前方法调用异步方法返回一个任务或任务并不将await运算符应用于结果.对异步方法的调用启动异步任务.但是,由于没有应用await运算符,程序会继续,而不会等待任务完成.在大多数情况下,这种行为不是你所期望的.通常调用方法的其他方面取决于调用的结果,或者最少,在从包含调用的方法返回之前,调用的方法应该完成.
同样重要的问题是在被调用的异步方法中引发的异常会发生什么.在返回任务或任务的方法中引发的异常存储在返回的任务中.如果您未等待任务或显式检查异常,则会丢失异常.如果等待该任务,则重新抛出异常.
作为最佳实践,您应该始终等待通话.
只有当您确定不想等待异步调用完成并且被调用的方法不会引发任何异常时,才应考虑禁止警告.在这种情况下,您可以通过将调用的任务结果分配给变量来抑制警告."
我的方式,编写异步方法的关键是让它运行,然后继续前进而不等待它完成
那你为什么await对Delay,如果这就是你相信什么?该Delay回报的任务; 你开始这项任务,你肯定要在它完成之前继续前进,然后再次进行下一次循环迭代?
当然不是.如果它以异步方式运行并且在没有人等待的情况下完成,那么这将打败延迟的整个点.
那究竟是什么await意思呢?它意味着它所说的:异步等待.也就是说: 在此任务完成之前,此工作流程无法继续,因此如果未完成,请查找其他工作并稍后返回.
这就是为什么通常你的异步方法的调用者会await得到结果.来电者是异步调用你,因为他们相信,工作流程需要一定的时间来完成,他们可以让他们的来电者做更多的工作,而他们是为你的方法来完成异步等待.
这就是你通常会做的,但你的方法并不正常. 你的方法永远不会完成!如果你做了await这个方法,你会等到它扔掉(因为它被取消),直到它正常完成,因为它没有正常完成!
因此await,您的方法返回的任务很可能在实践中永远等待,这不是您想要的.
因此,在这种情况下,您可以忽略或取消警告.但是在正常情况下,你正在调用一种方法,因为你要么想要它的副作用或者它的结果,要么你得到它就不能继续你的工作流程.所以你就是await这个任务,这样你的调用者就可以在你等待被调用者的工作流程完成时做更多的工作.
在编写更多异步代码之前,请确保绝对清楚.await是异步工作流的排序操作. 这意味着"在此任务完成之前,此工作流程将不会继续;请在等待时查找其他要做的事情,并在我们继续操作时返回".
将其与普通方法的"正常"调用进行比较. x = foo();表示"此工作流程将不会继续,直到调用foo完成;除了运行foo完成之外什么都不做".我们习惯于调用同步等待我们甚至不再考虑它的结果.
这个问题指出了C#类型系统的一个更大的设计问题.非泛型Task在逻辑上是"异步无效"; 也就是说,工作流程完成,但没有完成值. 对于永远不会正常返回但可能抛出的方法,C#没有类型系统概念.您可以想象一个特殊版本void,也许void never,这种方法中返回或具有可达终点是错误的.
您的工作流在逻辑上是"从不任务" - 它是一个无法正常完成的异步工作流程.如果编译器知道它然后它可以抑制警告(并且它可能在对它们之后具有无法访问的代码的方法的同步调用上产生警告never void.)但是编译器不知道因为这个概念不在类型系统中第一名.从逻辑上讲,它可能是,但我认为C#团队有更紧迫的问题.