为什么我必须使用wait来异步运行一个方法.如果我不;I don’我不想等到方法完成后再继续

本文关键字:方法 don 如果 再继续 我不想 一个 wait 异步 运行 为什么 | 更新日期: 2023-09-27 17:59:52

我一整天都在浏览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关键字)。

但是largerProcess方法不需要等待(即等待)报告方法完成才能执行bla-bla。然而,VS告诉我,使用异步方法,我可以等待它,或者它将同步发生,并阻止它。这不是违背了分开做的目的吗?

我该如何写这篇文章,以便报告SomethingHappened不会阻止大型进程的执行?(这本身就让我感到困惑,因为我一直认为这就是异步的意义所在)

为什么我必须使用wait来异步运行一个方法.如果我不;I don’我不想等到方法完成后再继续

如果调用异步方法,无论是否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,请查看ASP.Net 上的Fire and Forget