异步方法如何工作?

时间:2018-07-22 14:27:47

标签: c# winforms async-await

当我阅读有关asyncawait的Microsoft文档时,我不明白,

  

异步方法旨在作为非阻塞操作。等待   异步方法中的表达式不会阻塞当前线程   等待的任务正在运行。相反,该表达式将其余部分签名   方法的延续,并将控制权返回给的调用者   异步方法。

所以请考虑我的代码:

public  Form1()
{
    InitializeComponent();
    AsyncTest();
    Test(1);
}

private async void AsyncTest()
{
    HttpClient client = new HttpClient();
    var ss =  TT(2);

    var s = await ss;

    for (int i = 0; i < 10; i++)
    {
        //loop
    }
}

private async Task<int> TT(int i)
{
    while (true)
    {
        if (i  > 1000000000)
            break;
        i++;
     }

     return  i;
    }
}

每当我调用AsyncTest()时,它都会等待通过 await键指定的TT方法,但是它将控制权返回给主调用者是什么意思?? 它不会返回到form1,如果TT是一个无限循环,它将永远存在。 谢谢

1 个答案:

答案 0 :(得分:1)

在我看来,您是异步等待的新手。您违反了有关如何使用async-await的几条规则。

要使函数异步,请执行以下操作:

  • 声明异步功能
  • 返回Task<TResult>而不是TResult;返回Task而不是void
  • 仅例外:事件处理程序返回void而不是Task
  • 您的异步函数中应该有一个等待。如果省略此提示,编译器会警告您。
  • 在返回之前,请确保等待您调用的所有异步函数

指南:让async作为异步函数的后缀。这使您可以创建执行相同操作的同步和异步功能:void MyTest()Task MyTestAsync()

遵循这些规则,您不能从构造函数内部调用异步函数。在使用Winforms时,您的代码可能像这样:

public  Form1()
{
    InitializeComponent();
}

public async void OnButton1_Clicked(object sender, ...)
{   // because this is an event handler the return value is void

    // Start the first test and await until ready
    await TestAsync();

    // Start the second test and await until ready:
    int i = await TestAsync(1);
}

如果调用异步函数,则知道该函数内部的某个地方正在等待。如果在等待内部函数时有有意义的事情要做,请不要等待。通话结束后做一些有用的事情,并在需要结果后立即等待返回的Task:

public async void OnButton2_Clicked(object sender, ...)
{   
    // Start a test, but don't await yet
    var task1 = TestAsync(1);

    // if here, function TestAsync is awaiting somewhere
    // it is not finished yet, so you can't use the result of it
    // But you can do Something else:
    DoSomethingElse();

    // if here you really need the result of TestAsync, await for it
    int i = await task1;

    // if here you know that TestAsync is finished, i has the proper return value
}

您不必一个个地启动并等待任务,您可以启动多个任务并在需要结果时立即等待它们:

public async void OnButton3_Clicked(object sender, ...)
{   
    // start several tasks. Don't await yet:
    var task1 = TestAsync(1);
    var task2 = TestAsync(2);
    var task3 = TestAsync(3);

    DoSomethingElse();

    // if here I need the results of all three tasks:
    var myTasks = new Task[] {task1, task2, task3};
    await Task.WhenAll(myTasks);
}

this interview with Eric Lippert,确实对我帮助理解异步等待有所帮助,他将异步等待与做早餐的厨师进行了比较。如果厨师必须等待水沸腾,他不会闲着,而是四处看看是否可以做其他事情。在中间的某个地方搜索async-await。

另一篇帮助我遵循异步等待准则的文章是Async and Await by the ever so helpful Stephen Cleary