【问题标题】:How can I create call an async method inside another async method without it stalling如何在另一个异步方法中创建调用异步方法而不会停止
【发布时间】:2013-04-25 05:05:58
【问题描述】:

我需要调用多个异步方法,并在其中调用另一个异步方法。 让我演示一下

private async void button1_Click(object sender, EventArgs e)
{
    for(int i = 0; i< 100; i++)
    {
        await Method1();
    }
}

public async Task Method1()
{
    await Task.Delay(3*1000);
    await Method2();
}

public async Task Method2()
{
    await Task.Delay(10*1000);
}

我的问题是,for 语句仅在 Method2 的等待开始后激活迭代,而我想要的是一次创建 100 个任务。其他一切都将异步完成。

【问题讨论】:

    标签: c# winforms .net-4.5 async-await


    【解决方案1】:

    我认为您对“等待”的含义感到困惑。 “await”的意思是“开始异步处理这个东西,在这个过程中,回到windows消息循环并继续处理消息,以便UI继续重新绘制。当异步任务完成后,拿起我等待的代码”。

    所以当你 await 在这样的循环中时,你是在说:

    • 开始第一个异步作业...
    • 在它运行时,继续处理消息循环。
    • 当第一个异步作业完成时...
    • 在我们等待的循环中接机。我们绕过循环,然后...
    • 开始第二个异步作业...

    如果这不是你想要的,那么不要等待任务。如果您想启动一百个同时运行的任务,那么启动一百个任务并且不要等待其中任何一个。为什么点击处理程序中有 any await?

    【讨论】:

    • 异常情况如何?如果您不 await Task(或以其他方式处理其结果),则在执行 async 方法期间发生的任何异常都将被忽略。
    【解决方案2】:

    而不是 await-ing 在 for 循环中创建每个任务时,您只想启动所有任务。你不想将下一个任务的调度延迟到上一个完成,所以不要await

    private void button1_Click(object sender, EventArgs e)
    {
        for(int i = 0; i< 100; i++)
        {
            var task = Method1();
        }
    }
    

    完成。

    如果重要的是在所有任务完成后执行某项操作,同时仍并行执行所有任务,那么您可以依靠 Task.WhenAll 生成一个任务,该任务将在所有其他任务完成后完成:

    private async void button1_Click(object sender, EventArgs e)
    {
        var tasks = new List<Task>();
        for(int i = 0; i< 100; i++)
        {
            tasks.Add(Method1());
        }
        await Task.WhenAll(tasks);
        textbox1.Text = "Done!"; //or whatever you want to do when they're all done
    }
    

    【讨论】:

    • 我认为你应该几乎总是awaittask。使用您的第一个 sn-p,如果 Method1() 中有未处理的异常,它会默默地消失,我认为这是一件非常糟糕的事情。
    • 您的回答使我找到了解决方案,尽管它与您所说的不完全一样。谢谢
    • @svick 有很多方法可以处理异常。在不知道如果有人被抛出时您打算做什么的情况下,很难提出解决方案。您可以添加一个 onerror 延续,您可以确保在 Method1 中处理错误而不是来自调用者(如果需要,将其包装在另一个方法中以处理异常)等等。
    • @jure 你为什么要这样做?该方法是异步的,因此并行启动它不太可能给您带来任何性能提升。
    • @Svick 我对并行编程不是很有经验。从来不需要使用大量的并行处理,所以这更多是我的问题。 Servy 在一个 for 循环中提议的启动 100 个任务是否与使用 Parallel.For 启动它相同?
    猜你喜欢
    • 1970-01-01
    • 2014-09-13
    • 2012-02-09
    • 1970-01-01
    • 2017-04-27
    • 2013-08-07
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多