【问题标题】:not understanding of async await concept [duplicate]不了解异步等待概念[重复]
【发布时间】:2020-12-17 01:14:25
【问题描述】:

当我阅读有关 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() 时,它只是在 TT 方法后面等待,因为它使用 await 键 指定,但这意味着什么它将控制权返回给主调用者 ?? 它不会返回到 form1,如果 TT 是一个无限循环,它就会永远保持下去。 谢谢

【问题讨论】:

  • 编译此代码时,您会收到一个编译器警告,指出TT 不包含await 运算符,它将同步运行。我建议您根据该警告进行研究,这样会更清楚发生了什么
  • 您的 for 循环是 CPU 密集型的,不是异步 I/O 的良好替代品。

标签: c# winforms async-await


【解决方案1】:

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

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

  • 声明函数异步
  • 返回Task&lt;TResult&gt; 而不是TResult;返回Task 而不是void
  • 只有例外:事件处理程序返回 void 而不是 Task
  • 您的异步函数中应该有一个 await。如果你省略了这个,你的编译器会警告你。
  • 确保在返回之前等待您调用的所有异步函数

指南:让 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);
}

如果你调用一个异步函数,你就会知道这个函数内部的某个地方是等待。如果您在内部函数等待时有有意义的事情要做,请不要等待。在调用后做你有用的事情,并在需要结果时立即等待返回的任务:

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);
}

真正帮助我理解 async-await 的文章是 this interview with Eric Lippert,,他将 async-await 与做早餐的厨师进行了比较。如果一个厨师要等水烧开,他不会无所事事,而是四处张望,看看能不能做点别的事情。在中间某处搜索 async-await。

另一篇帮助我遵循 async-await 准则的文章是 Async and Await by the ever so helpful Stephen Cleary

【讨论】:

  • 非常感谢,实际上我无法理解 async await 和在新 thread 中调用方法之间的区别!看来他们都是并行的!
  • 显然你还没有读过我建议的 Eric Lipprt?异步等待:一位厨师做早餐。每次他要等水烧开的时候,他都会四处看看,看看能不能做点别的,而不是无所事事地等待。新线程 = 在你闲着等水的时候雇个厨师做点别的事
猜你喜欢
  • 1970-01-01
  • 2018-04-17
  • 2014-01-09
  • 2013-05-16
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
  • 2019-06-29
  • 1970-01-01
相关资源
最近更新 更多