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

标签 c# .net asynchronous async-await .net-4.5

<分区>

我整天都在翻阅 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,等待 web 请求,并添加 async 关键字)。

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

我该如何编写才能使 reportSomethingHappened 不会阻止 largerProcess 的执行? (这本质上让我感到困惑,因为我一直认为这就是异步的意义所在)

最佳答案

如果您调用一个异步方法,无论您是否等待返回的任务,它都会异步运行。

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

关于c# - 为什么我必须使用等待异步运行的方法。如果我不想在继续之前等待方法完成怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31078849/

相关文章:

c# - 如何阻止枚举越界?

c# - 独特的对集合

unit-testing - XCTestExpectation : API violation - multiple calls made to -[XCTestExpectation fulfill] 错误

c# - 对 .Net 任务进行排序

c# - .NET 类库中的 IAudioEndpointVolume 位于何处?

ios - 在 Swift 中加载其他元素后,在 TableViewCell 中异步加载一个元素

c# - 如何删除 Access Db 的临时 ldb 文件

c# - 如何区分USB和软盘设备?

c# - 如何使用 dbAutoTrack 使用 DrawTable

c# - 摆脱滚动列表框中的额外空间