C# 忽略异步任务方法的返回值
下面是一个场景:在我的WPF应用程序中,我希望始终保持一个循环运行,以完成各种事情。我想到了这种模式:C# 忽略异步任务方法的返回值,c#,async-await,compiler-warnings,C#,Async Await,Compiler Warnings,下面是一个场景:在我的WPF应用程序中,我希望始终保持一个循环运行,以完成各种事情。我想到了这种模式: void MainWindow_OnLoaded(object sender, RoutedEventArgs e) { SomeProcessAsync(); //throw away task } async Task SomeProcessAsync() { while (true) {
void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
SomeProcessAsync(); //throw away task
}
async Task SomeProcessAsync()
{
while (true)
{
DoSomething();
await Task.Delay(1000);
}
}
调用会触发警告,因为返回值未使用。什么是消除这一警告的最干净的方法
#pragma warning disable 4014
AddItemsAsync(); //throw away task
#pragma warning restore 4014
这很管用,但看起来很恶心
顺便说一句,我也可以使用计时器,但我喜欢这个循环的简单性。您可以使事件处理程序异步:
async void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
await SomeProcessAsync(); //throw away task
}
通常,
async void
是不好的,但是当事件处理程序是异步的,异常应该在这里处理,而不是在任何调用它的地方。如果SomeProcessAsync
不需要UI上下文,您可以(也应该)使用普通的ConfigureAwait(false)
。最好使用代理代码创建任务
Task.Factory.StartNew(()=>{}) 我的解决方案是使用一个可重用的小助手方法来消除编译器警告:
static class TaskHelpers
{
/// <summary>Signifies that the argument is intentionally ignored.</summary>
public static void DiscardTask(this Task ignored)
{
}
}
这是干净和自我记录。仍然在为帮助程序寻找更好的名称。正如chris的回答中已经提到的,正确的解决方案是将事件处理程序转换为
异步void
方法,然后使用wait
,以便正确传播异常
但是,如果确实要忽略任务
,则可以将其分配给变量:
var ignored = SomeProcessAsync();
或者在C#7.0中,您可以使用discard:
_ = SomeProcessAsync();
Async await使用线程池中的线程。尽管线程池中的线程数量相当大,并且可能是可调整的,但它仍然是有限的线程数量 线程池中的线程针对短期任务进行了优化。它们的开始和结束都很快,这些线程的结果可以相当容易地访问。但这些优势是有代价的。否则,所有线程都将是线程池中的线程
如果你想让你的线程在相当长的一段时间内完成一些事情,最好使用一个常规的System.Threading.thread,可能包装在System.ComponentModel.BackgroundWorker中。使用
void
作为返回类型怎么样?为什么你首先有两种方法?只要在main窗口中加载循环即可
。为什么不使用计时器代替此循环<代码>任务。延迟本身在下面使用计时器。这不是一个“先发后忘”的任务,只要表单或应用程序处于活动状态,它就应该处于活动状态。如果不需要它的特定行为,我希望避免async void。此外,SomeProcessAsync方法不需要知道调用它的代码。它应该公开该任务,而放弃它是调用方的工作。@这是一个很好的观点,但假设已经有一个大的负载处理程序,问题又变得相关了。这将无法访问UI控件。当然,可以使用Dispatcher.BeginInvoke+++作为UIcall@GCamel听起来你以前从未使用过TPL。使用TPL时,如果您正在呼叫BeginInvoke
,几乎肯定是做错了什么。无论如何,这并不能以任何方式解决问题;您仍然在放弃一项任务
,您只是在创建额外的工作,而这些工作在这个过程中并没有完成任何有成效的工作(并且会对许多代码造成积极的损害)。@GCamel不,它们不是。它们是等待已经执行的任务的一种方式。至于挑逗Servy。。。好吧,你不会因为async/await
评论而获得金质徽章。ViewModels和数据绑定也与当前问题无关。重新发布以前的注释,因为它完全适用:如果不需要async void的特定行为,我希望避免它。此外,SomeProcessAsync方法不需要知道调用它的代码。它应该公开任务,而放弃它是调用方的工作。也许在这段简单的代码中,这项技术还可以,但我想找到一个通用的解决方案。因此,您正在寻找的解决方案是,当您需要一个同步方法来使用异步方法时。事件处理程序不是一个很好的例子,因为它可以是异步的。最好在原来的问题中列入这一要求。我不确定您在需要时保存的async void
的具体行为是什么-据我所知,异常是一个问题,但您打算捕获的异常转义事件处理程序也是一个问题。此外,该代码对@boot4life调用异步方法并将任务放在地板上的SomeProcessAsync
@boot4life没有任何要求,其功能与async void
方法相同。async void
方法的问题是,您强制调用方将任务放在地板上,这就是为什么在实际不是所需行为的情况下使用它是有问题的。有趣的是,我在这里没有收到编译器警告。编译器团队一定考虑过这种情况。检查并。在意大利,DiscardTask
扩展方法将被称为ForgetAboutIt
。
_ = SomeProcessAsync();