使用不带等待功能的异步函数,该函数包含另一个返回void的函数

时间:2019-11-20 14:49:36

标签: c# async-await

所以我有这个WrapperFunction,它试图使FunctionReturningVoid被异步调用:

    public async Task WrapperFunction()
    {
        this.FunctionReturningVoid("aParameter");
    }

这是什么都不返回的函数。在代码的某些部分(此处未详述)中,它被称为SYNChronously,但在CallerFunction()中,我们希望它在ASYNChronously中运行。

    public void FunctionReturningVoid(string myString)
    {
        Console.Write(myString);
    }

这是已实现异步的函数,需要WrapperFunction来完成其工作而不会阻塞otherStuff()。

    public async Task CallerFunction()
    {
        await WrapperFunction():
        int regular = otherStuff();
        ...
    }

IDE警告我WrapperFunction没有使用await:

  

此异步方法缺少“等待”运算符,将同步运行。   考虑使用“ await”运算符来等待非阻塞API调用,   或“ await Task.Run(...)”在后台线程上执行CPU绑定工作。

问题:如何在WrapperFunction中使用异步而不使用等待?如果我使用await,它告诉我不能等待void。

1 个答案:

答案 0 :(得分:5)

区分异步与并行非常重要。

异步意味着您在等待某些事情发生时不会阻塞当前线程。这样,当前线程可以在等待时执行其他操作。

平行意味着同时做一件事。这需要为每个任务使用单独的线程。

您不能异步调用FunctionReturningVoid,因为它不是异步方法。在您的示例中,Console.WriteLine()的编写方式将阻塞线程直到完成。您无法更改。但我知道这只是您针对此问题的示例。如果您的实际方法正在执行某种I / O操作,例如网络请求或写入文件,则可以将其重写为使用异步方法。但是,如果它正在执行CPU繁重的工作,或者您无法重写它,那么您就被它保持同步-它在运行时阻塞当前线程。

但是,您可以 (在另一个线程上)并行运行FunctionReturningVoid并异步等待它(这样它就不会阻塞当前线程)。如果这是桌面应用程序,这将是明智的选择-您不想在运行时锁定UI。

为此,您可以使用Task.Run,它将开始在另一个线程上运行代码,并返回一个Task,您可以使用它来了解它何时完成。这意味着您的WrapperFunction如下所示:

public Task WrapperFunction()
{
    return Task.Run(() => this.FunctionReturningVoid("aParameter"));
}

观点:注意,我删除了async关键字。这是没有必要的,因为您可以将Task传递给调用方法。有关此here的更多信息。

Microsoft有一些有关Asynchronous programming with async and await的写得很好的文章,值得一读。