如何在不等待的情况下在.NET中调用异步函数

时间:2019-03-14 16:32:16

标签: c# .net async-await

我在C#中具有如下异步功能:

private static async Task AddEmoji(string emoji)
{
   ...
}

在某些情况下,我想调用它,但是我不想等待它的结果,并且我不在乎它是否有效。解决这个问题的正确方法是什么?我以为可以不添加async参数就可以调用它:

AddEmoji("");

...可以,但是VS给了我CS4014编译警告,所以我猜这是不对的。然后,我尝试为其创建一个任务:

Task.Run(() => await AddEmoji(""));

但这给了我一个实际的编译错误:

  

错误CS4034'await'运算符只能在异步中使用   lambda表达式。考虑使用标记该Lambda表达式   “异步”修饰符。

解决这个问题的正确方法是什么?

3 个答案:

答案 0 :(得分:0)

在Task.Run()中,等待不会进入Func <>内部。您通常会在Task本身上等待(将await放在Task.Run()之前),但是我认为在您的情况下,您可以省略await以便不等待并忽略结果:

Task.Run(() => AddEmjoi(""))

答案 1 :(得分:0)

  

我不想等待其结果,也不在乎它是否有效。

极端与众不同;首先要检查的是这种假设,即您实际上不需要知道它何时完成(或 if 它完成),并且可以无声地忽略所有异常。这也意味着,当您的应用退出时,您可以永不完成这项工作(并且再次,您将不会知道,因为会忽略异常)-请记住,在诸如ASP.NET的托管方案中,您在您的应用退出时不受控制

也就是说,您可以这样“抛弃”:

var _ = AddEmoji("");

答案 2 :(得分:-3)

这不适用于asp.net-asp.net应用程序中不允许使用async void方法。控制台,WPF,Winforms等应用程序也可以。请参阅注释以获取完整的讨论。

最好的方法是在await方法内async void

仅写AddEmoji("");的问题是:如果失败,会发生什么?如果在AddEmoji中引发了异常,则该异常将捆绑在Task返回的AddEmoji中。但是,由于您丢掉了Task,所以您永远不会知道。因此AddEmoji可能会以失败的方式失败,但是您永远不会知道。这就是为什么编译器给您一个错误。

但是,async void方法避免了这种情况。如果在async void方法中引发了异常,则该异常将重新引发到ThreadPool上,这将导致您的应用程序崩溃。您肯定会知道出了什么问题!

人们建议不要使用async void方法,但是它们非常适合一劳永逸的情况。这些建议源于人们在想知道何时完成操作时尝试使用async void方法的人。

public async void AddEmojiImpl(string emoji) => await AddEmoji(emoji);

public async void AddEmojiImpl(string emoji)
{
    try 
    {
        await AddEmojiImpl(emoji);
    }
    catch (EmojiAddException e)
    {
        // ...
    }
}

本地功能对此特别有用。