声明没有async关键字的方法返回类型Task <int>

时间:2019-02-16 05:58:46

标签: c# async-await task

在什么情况下您不使用方法签名中的Task<T>来返回async

我在下面的代码中有这样一种方法,但是在了解发生了什么情况时遇到了麻烦。

为什么下面的示例代码无法通过任何await语句执行? 即。为什么Console.WriteLine("4)");Console.WriteLine("3)");return x;永远不会执行?

class Program
    {
        static void Main(string[] args)
        {
            TestAsync testAsync = new TestAsync();
            testAsync.Run();

            Console.Read();
        }
    }

    public class TestAsync
    {
        public async void Run()
        {
            Task<int> resultTask = GetInt();
            Console.WriteLine("2)");
            int x = await resultTask;
            Console.WriteLine("4)");
        }
        public async Task<int> GetInt()
        {
            Task<int> GetIntAfterLongWaitTask = GetIntAfterLongWait();
            Console.WriteLine("1)");
            int x = await GetIntAfterLongWaitTask;
            Console.WriteLine("3)");
            return x;
        }

        public Task<int> GetIntAfterLongWait()
        {            
            Task.Run(() =>
            {
                for (int i = 0; i < 500000000; i++)
                {
                    if (i % 10000000 == 0)
                    {
                        Console.WriteLine(i);
                    }
                }
            });

            Console.WriteLine("Returning 23");
            return new Task<int>(() => 23);
        }
    }

/*
Output is:
Returning 23
1)
2)
<list of ints>
*/

3 个答案:

答案 0 :(得分:4)

当您通过非Task方法返回async时?

Task<T>是针对未来值的 promise 通用称呼。无论是从关键字async的方法还是从另一个源(例如启动的线程或IO回调)产生此承诺,调用者都不会感兴趣,而只是实现策略。这也是为什么接口(或抽象方法定义)根本没有async关键字(async / await是一种实现策略)的原因。

您的代码示例

  • 问题1 :您的方法GetIntAfterLongWait有两种缺陷。实例化的第一个实例化Task并卸载到线程中,但是结果从未被提取(因此从未等待过……也从未延迟任何事情)。
  • 问题2 :创建第二个任务(您在GetIntAfterLongWait中返回的任务)(由具有执行方法的构造函数创建),但未启动(Task.Start()) 。其他更简单的方法是静态Task.Run或(在这种情况下)Task.FromResult。任务(或承诺)从不交付结果,因为构造函数中的功能块从不执行。
  • 问题3 Main方法不等待返回任务的结果(通过awaitTask.Wait()Task.Result

答案 1 :(得分:0)

您可能会在GetIntAfterLongWait()方法中创建一个新线程。尝试将return new Task<int>(() => 23);更改为return Task.FromResult(23);

有关Task.FromResult的更多信息,请参见How to: Create Pre-Computed Tasks上的MSDN文档(有一个很好的例子)

答案 2 :(得分:0)

代码中的问题是实际上您await从未启动过任务,因为方法GetIntAfterLongWait返回了尚未启动的新任务实例。所以基本上您有一个僵局,等待根本无法开始的事情。

您可以返回Task.FromResult(23),该任务基本上已经完成,或者您可以实际运行任务Task.Run<int>(() => 23);