C# 无法理解异步等待行为?

C# 无法理解异步等待行为?,c#,multithreading,asynchronous,task-parallel-library,async-await,C#,Multithreading,Asynchronous,Task Parallel Library,Async Await,我有以下代码 using System; using System.Threading.Tasks; namespace asyncawait { class Practice { async Task<int> Method() { for (int i = 0; i < int.MaxValue ; i++); return 10; } pu

我有以下代码

using System;
using System.Threading.Tasks;


namespace asyncawait
{
    class Practice
    {
       async Task<int>  Method()
        {
            for (int i = 0; i < int.MaxValue ; i++);

            return 10;
        }

       public async void caller()
        {

           int a = await Method();
           Console.WriteLine("Please print it first");
           Console.WriteLine(a);
           Console.WriteLine("Please print it last");

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Practice p = new Practice();
            p.caller();
        }
    }
}
创建项目时发出警告:

Program.cs9,25,9,31:警告CS1998:此异步方法缺少“wait” 运算符和将同步运行。考虑使用“等待” 运算符等待非阻塞API调用,或“等待任务.运行…”等待 在后台线程上执行CPU绑定的工作

我的期望是,

预期输出:第一行应立即打印

请先打印//no wait,因为我没有使用,函数为wait 10 请最后打印

实际产量:

请先打印//等待执行函数,然后打印输出 10 请最后打印


我不明白,为什么我的函数需要时间才能异步工作?在看了很多例子之后,我真的无法理解这个概念。

尝试用以下代码替换主要方法的代码:

Task.Run(
() =>
{
      Practice p = new Practice();
      p.caller();
});
您将得到答案。

async关键字只允许您在函数中使用wait关键字。如果不调用wait,则函数的行为与根本不执行任何async关键字的行为相同

请从msdn页面查看此图像

如果你沿着黑线走,所有的事情都发生在同一条线上,一直持续到6点。然后,在这一点上,函数返回,并在结果就绪后继续。因为代码中没有等待,所以黑线贯穿了整个函数

要使它像您希望的那样工作,您需要在函数中发出信号,指出它应该返回给调用者的位置

   async Task<int>  Method()
    {
        for (int i = 0; i < int.MaxValue ; i++)
        {
            await Task.Yield(); //Your function now returns to the caller at this point then comes back later to finish it. (Your program will be much slower now because it is going to wait int.MaxValue times.)
        }
        return 10;
    }
当您使用wait关键字时,您告诉当前方法等待您传递给它的任务的结果。神奇之处在于,在等待过程中,方法被挂起,调用线程可以继续其他工作

当您将await方法作为第一条语句时,函数的其余部分仅在方法的结果可用后执行,而不管函数外部在这两条语句之间发生了什么。要实现所需的行为,应首先启动任务,然后打印第一行,然后等待结果。即:

public async void caller() {
    var a = Method();   // <- The task is running now asynchronously
    Console.WriteLine("Please print it first"); // <- The line is printed.
    Console.WriteLine(await a); // <- the result of a is waited for and printed when available.
    Console.WriteLine("Please print it last");
}

您应该看看这篇文章中的答案:请参阅Eric Lippert的一篇优秀文章:该方法上的“async”修饰符并不意味着“该方法自动安排在工作线程上异步运行”。它的意思正好相反;诸如此类。你们可能会发现我的帮助。没关系,因为方法是一个同步函数,他仍然会看到它暂停。当方法返回时,任务已经处于已完成状态,因此移动等待不会改变任何东西。你说得对,我错过了,抱歉。我修正了我的答案。挑剔:异步方法将不完全相同-它将自动在任务中包装任何返回值。但这是唯一的区别。
Task<int> Method() {
    return Task.Run( () => {
        // ... the previous function body...
    });
}