C# 在没有wait关键字的情况下调用异步方法会发生什么?

C# 在没有wait关键字的情况下调用异步方法会发生什么?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我有一个web服务器,有一个定期的作业合并和发送记录(大量请求日志) 在MergeAndPutRecords函数中,有代码合并记录,异步函数返回任务发送记录。(事实上,这是亚马逊动力消防队的。) 那么,如果我在没有wait关键字的情况下调用该函数,会发生什么呢?函数是否在单独的线程上运行。那么返回任务意味着什么?表示不带wait关键字的异步方法 在当前线程上启动异步方法。忽略所有结果(包括异常) 那么我的定期作业和PutRecordBatchAsync是否同时处理?我知道异步和并发是不同的。但并

我有一个web服务器,有一个定期的作业合并和发送记录(大量请求日志)

MergeAndPutRecords
函数中,有代码合并记录,异步函数返回任务发送记录。(事实上,这是亚马逊动力消防队的。)

那么,如果我在没有wait关键字的情况下调用该函数,会发生什么呢?函数是否在单独的线程上运行。那么返回任务意味着什么?表示不带wait关键字的异步方法

  • 在当前线程上启动异步方法。忽略所有结果(包括异常)
  • 那么我的定期作业和PutRecordBatchAsync是否同时处理?我知道异步和并发是不同的。但并没有等待关键字,它们在同一个线程中。哪一个会先被处决?我很困惑


    将有大量记录需要合并并实时发送。因此,我认为它必须同时执行。

    如果一个方法返回一个
    任务
    ,最好的做法是在某个点观察该
    任务的结果。它可能是声明的返回值,也可能是异常。如果要在方法继续之前观察该任务,建议使用
    wait

    在这种情况下,您可能应该观察由
    PutRecordBatchAsync
    返回的
    任务的结果。您需要知道呼叫是否因任何原因失败,因为这可能表明您的记录未存储

    在您给出的示例代码中,您会发现在上一次调用完成之前,您对
    MergeAndPutRecords
    进行了后续调用。你确定这是有意的吗

    那么我的定期作业和PutRecordBatchAsync是否同时处理

    通过使用任务API,您可以确保它们是并发执行的(使用线程池),但您需要了解内存中并发操作与基于IO的并发之间的区别

    虽然内存中的并发性确实有利于使用任务,但IO调用一旦执行就根本不需要线程,因为它依赖于硬件并发性,如果它使用线程,那么它将等待IO调用返回,从而浪费宝贵的系统资源并降低系统可伸缩性

    您的案例是基于IO的并发,正如您调用基于远程/网络的API一样,异步如何在这里等待帮助

    真正的异步操作将释放线程上下文,在windows上,它将使用IO完成端口(队列机制)执行异步调用,而调用线程用于调度其他类似调用,它只需要在IO调用返回时使用线程上下文来服务响应,如果不是UI调用,然后使用
    ConfigureAwait(false)
    ,以便可以使用任何线程上下文来传递响应

    如果不将wait与async一起使用呢


    本来是异步的调用会变成同步的,并且会立即影响系统的可伸缩性,因为线程现在被阻塞,对于长时间运行的IO操作来说更糟。您已经看到JavaScript框架如何始终对服务器API进行AJAX(异步)调用,因此在阻止浏览器线程的情况下可能需要做更多的工作

    一般来说,对于内存处理,您会创建一定数量的任务,并使用
    Task.WaitAll
    并行处理它们。ForEach
    对于集合,对于异步处理,理想的建议是不要有
    任务。在任何地方运行
    ,最好从入口点开始执行
    异步
    ,与MVC一样,控制器可以是异步的。多个呼叫使用
    Task.whalll
    representative Task组合在一起,然后等待。即使使用了
    Task.Run
    ,也要像在代码中一样,然后使用
    async lambda
    执行异步调用

    总结:


    异步调用必须使用
    await
    ,否则它们的
    async
    关键字在该上下文中是无用的,yes
    await
    将在继续执行之前等待IO调用返回,尽管进程中没有线程被阻止
    async
    关键字本身不做任何事情。每个
    wait
    组合成一个
    asynchStateMachine
    ,可以异步处理内容。如果在
    async
    方法中没有
    await
    关键字,那么就没有理由创建
    AsyncStateMachine
    ,所以就得到了同步方法。
    await
    用于等待结果到达。它不以任何方式控制获取结果的进程是如何启动的,也不控制获取结果的正在进行的进程是如何工作的。“原本是异步的调用会变成同步的,并且会立即影响系统的可伸缩性,因为线程现在被阻塞”-我认为这是不正确的或不清楚的。是的,对异步函数的调用是同步返回的,但从概念上讲它总是同步返回;异步性在wait语句中“发生”。如果wait不存在,则调用方将无序地通过异步函数。如果任务有延续,它仍然运行,但实际上是无头的;结果和异常被忽略。(1/3)让我们在正确的上下文中理解该语句,IO调用异步处理的本质是将处理转移到后台,不阻塞任何等待后台进程完成的进程线程,从而确保更高的可伸缩性,因为在windows中,每次执行都发生在线程上,空闲等待是非常不可取的。
    wait
    所做的是创建一个状态机,它捕获当前的执行上下文,用于后续返回。在一系列方法调用中,实际的异步处理在调用离开进程边界(2/3)时开始,在此之前,我们希望每次调用都是这样
    Task.Run(() =>
    {
        while (true)
        {
            try
            {
                MergeAndPutRecords();
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
        }
    });