【问题标题】:Async method not returning control back to caller method异步方法不将控制权返回给调用方方法
【发布时间】:2019-06-14 11:40:51
【问题描述】:

我有以下代码

class Program
{
    public  async  Task<bool> StartMyTask()
    {
        await Foo();

        return true;

    }

    public async Task<bool> Foo()
    {

        for (int i = 0; i < 1000000; i++)
        {
            Console.WriteLine("Loop");
        }
        return true;

    }


    static void Main(string[] args)
    {
        Program obj = new Program();

        var myTask = obj.StartMyTask();     
        Console.WriteLine("Before Task Return");                                    


        Console.ReadLine();
    }
}

根据我的理解,当“await Foo()”被调用时,将创建一个线程来执行“Foo()”方法,并将控制权返回给调用者(Main 方法)。

考虑到这一点,应该在“Foo()”方法完成之前打印“Before Task Return”。但它没有发生,首先“Foo()”方法完成,然后显示“Before Task Return”。

【问题讨论】:

  • 你的理解是错误的,没有为Foo创建线程,并且由于它实际上并没有做任何异步工作,所以它会阻塞直到循环完成。
  • 简而言之,那些不做任何真正异步工作的异步方法与非异步工作相同。
  • 不,不是您编写代码的方式。正如我所说,您对 async/await 的理解是错误的。这两个关键字都不会创建新线程。由于您实际上在这里没有进行异步工作,因此您的代码的行为与删除 async/await 关键字并同步执行所有操作时完全相同。
  • 由于你的 Async 没有等待任何东西,它会同步运行。您应该会在编译器中收到有关此效果的警告。
  • 简短版:async != 线程(它们是相关主题,但不一样

标签: c# multithreading async-await


【解决方案1】:

根据我的理解,当“await Foo()”被调用时,将创建一个线程来执行“Foo()”方法,并将控制权返回给调用者(Main方法)。

不,绝对不是。 asyncawait 不会自行创建线程。 async allows you to use await, and await will "asynchronously wait" - i.e., pause the method, return, and then resume the method when its operation completes.

请注意,编译器会警告您有一个标记为async 的方法,但它将同步运行。所以编译器已经准确地告诉你出了什么问题。

如果您使用后台线程,可以使用Task.Run 调用同步的Foo 方法:

public async Task<bool> StartMyTask()
{
  await Task.Run(() => Foo());
  return true;
}

public bool Foo()
{
  for (int i = 0; i < 1000000; i++)
  {
    Console.WriteLine("Loop");
  }
  return true;
}

【讨论】:

  • 在世界上的 Stephen Clearys 和 Eric Lipperts 能够回答之前,我正狂热地试图回答这个问题。哦,好吧。
  • 我在等他的答复。
  • 当你说control goes back to caller时,请你告诉我调用者是否使用与调用await函数相同的线程来执行后续代码?
  • @variable:是的。从运行时的角度来看,线程调用了一个返回任务的方法。方法返回后线程继续执行。
  • 那为什么说线程在await时返回线程池。
【解决方案2】:

由于您的 Foo 方法不会创建任何任务,因此您的代码不会像您期望的那样发散,但如下所示可以解决您的问题:

public async Task<bool> Foo()
    {
       return await Task.Run(() =>
       {
           for (int i = 0; i < 100000; i++)
           {
               Console.WriteLine("Loop");
           }
           return true;
       });
    }

【讨论】:

    猜你喜欢
    • 2014-09-22
    • 2017-05-19
    • 1970-01-01
    • 2014-10-22
    • 2013-11-14
    • 1970-01-01
    • 2019-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多