所以我有这个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。
答案 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的写得很好的文章,值得一读。