为什么我必须异步使用 await 方法 运行 。如果我不想在继续之前等待方法完成怎么办?
Why do I have to use await for a method to run asynchronously. What if I don't want to wait for the method to finish before continuing?
我整天都在翻阅 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() 变成异步方法(据我所知,等待 web 请求,并添加异步关键字)。
但是 largerProcess 方法不需要等待(即等待)报告方法完成以执行 bla bla。然而,VS 告诉我,使用异步方法我可以等待它,或者它会同步发生并阻塞。这不是违背了分开做的目的吗?
我该如何编写才能使 reportSomethingHappened 不会阻止 largerProcess 的执行? (这本质上让我感到困惑,因为我一直认为这就是异步的意义所在)
如果您调用异步方法,无论您是否 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
我整天都在翻阅 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() 变成异步方法(据我所知,等待 web 请求,并添加异步关键字)。
但是 largerProcess 方法不需要等待(即等待)报告方法完成以执行 bla bla。然而,VS 告诉我,使用异步方法我可以等待它,或者它会同步发生并阻塞。这不是违背了分开做的目的吗?
我该如何编写才能使 reportSomethingHappened 不会阻止 largerProcess 的执行? (这本质上让我感到困惑,因为我一直认为这就是异步的意义所在)
如果您调用异步方法,无论您是否 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