这个问题在这里已有答案:
我整天都在倾听MSDN文档,他们的异步编码理念让我感到困惑。据我了解,如果调用异步方法,则不会阻止调用异步方法的线程。然而,async总是与await配对,这似乎否定了异步,使得外部方法必须等待代码执行。我不应该能够调用异步方法然后继续执行外部方法吗?
这是我遇到的情景,或多或少:
void reportSomethingHappened(info)
- Collect info
- HTTP POST info to logging server (ie. mixpanel, sentry)
这里将是一个调用方法:
void largerProcess
if (whatever)
reportSomethingHappened();
bla;
bla;
据我所知,由于POST请求可以异步完成,我应该能够将reportSomethingHappened()转换为异步方法(通过,AFAIK,等待webrequest,并添加async关键字)。
但是largeProcess方法不需要等待(即等待)报告方法完成以执行bla bla。然而,VS告诉我,使用异步方法我可以等待它,或者它将同步发生,然后阻塞。这不是单独打败它的目的吗?
我怎么写这个,以便reportSomethingHappened不会阻止greaterProcess的执行? (这本身就让我感到困惑,因为我认为这一直是异步的重点)
如果你调用异步方法,它将异步运行,无论你是否await
返回的任务。
await
不影响方法的执行方式,只影响调用者处理它的方式。您可以调用异步方法,获取任务并立即等待它(这是最简单的选项)。这将使您能够编写看起来同步但异步运行的代码,因为await
基本上将其余的代码注册为它后面的回调,只有在等待的任务完成后才能执行。这不会阻止传统,因为没有线程被阻止,但代码流将是顺序的:
async Task LargerProcessAsync()
{
if (condition)
{
await ReportSomethingHappenedAsync();
}
// do other stuff
}
但是,您并不一定非要这样做。你可以恢复任务,做其他的事情,然后await
它:
async Task LargerProcessAsync()
{
Task task = null;
if (condition)
{
task = ReportSomethingHappenedAsync();
}
// do other stuff
if (task != null)
{
await task;
}
}
或者你可以完全删除await
。你应该意识到,这可能是危险的,因为任务可能会出现故障而异常无法被观察到,这就是为什么不鼓励这样做的原因。有几种方法可以做到这一点,但它们并不简单。你可以使用Task.ContinueWith
:
void LargerProcess()
{
if (condition)
{
ReportSomethingHappenedAsync().ContinueWith(task =>
{
try
{
task.Wait();
}
catch (Exception exception)
{
// handle exception
}
})
}
// do other stuff
}
或者ASP.Net看看Fire and Forget on ASP.NET