为什么我必须使用等待方法来异步运行.如果我不想在继续之前等待方法完成怎么办?

the*_*her 13 .net c# asynchronous async-await .net-4.5

我整天都在倾听MSDN文档,他们的异步编码理念让我感到困惑.据我了解,如果调用异步方法,则不会阻止调用异步方法的线程.然而,async总是与await配对,这似乎否定了异步,使得外部方法必须等待代码执行.我不应该能够调用异步方法然后继续执行外部方法吗?

这是我遇到的情景,或多或少:

void reportSomethingHappened(info)
    - Collect info
    - HTTP POST info to logging server (ie. mixpanel, sentry)
Run Code Online (Sandbox Code Playgroud)

这里将是一个调用方法:

void largerProcess
    if (whatever)
        reportSomethingHappened();
    bla;
    bla;
Run Code Online (Sandbox Code Playgroud)

据我所知,由于POST请求可以异步完成,我应该能够将reportSomethingHappened()转换为异步方法(通过AFAIK,等待webrequest,并添加async关键字).

但是largeProcess方法不需要等待(即等待)报告方法完成以执行bla bla.然而,VS告诉我,使用异步方法我可以等待它,或者它将同步发生,然后阻塞.这不是单独打败它的目的吗?

我怎么写这个,以便reportSomethingHappened不会阻止greaterProcess的执行?(这本身就让我感到困惑,因为我认为这一直是异步的重点)

i3a*_*non 19

如果调用异步方法,无论是否await返回任务,它都将异步运行.

await不影响方法的执行方式,只影响调用者处理它的方式.您可以调用异步方法,获取任务并立即等待它(这是最简单的选项).这将使您能够编写看起来同步但异步运行await的代码,因为它基本上将其余代码注册为回调,只有在等待的任务完成后才能执行.这不会阻止传统,因为没有线程被阻止,但代码流将是顺序的:

async Task LargerProcessAsync()
{
    if (condition)
    {
        await ReportSomethingHappenedAsync();
    }

    // do other stuff
}
Run Code Online (Sandbox Code Playgroud)

但是,您并不一定非要这样做.你可以恢复任务,做其他事情,然后await才能:

async Task LargerProcessAsync()
{
    Task task = null;
    if (condition)
    {
        task = ReportSomethingHappenedAsync();
    }

    // do other stuff

    if (task != null)
    {
        await task;
    }
}
Run Code Online (Sandbox Code Playgroud)

或者你可以完全删除await.你应该意识到,这可能是危险的,因为任务可能会出现故障而异常无法被观察到,这就是为什么不鼓励这样做的原因.有几种方法可以做到这一点,但它们并不简单.你可以使用Task.ContinueWith:

void LargerProcess()
{
    if (condition)
    {
        ReportSomethingHappenedAsync().ContinueWith(task => 
        {
            try
            {
                task.Wait();
            }
            catch (Exception exception)
            {
                // handle exception
            }
        })
    }

    // do other stuff
}
Run Code Online (Sandbox Code Playgroud)

或者对于ASP.Net,请查看ASP.NET上的Fire和Forget