C# 忽略异步任务方法的返回值

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) {

下面是一个场景:在我的WPF应用程序中,我希望始终保持一个循环运行,以完成各种事情。我想到了这种模式:

    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();