代码之家  ›  专栏  ›  技术社区  ›  David Klempfner

声明方法返回类型task<int>而不使用async关键字

  •  1
  • David Klempfner  · 技术社区  · 6 年前

    在什么情况下您会返回 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>
    */
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   Johnny    6 年前

    代码中的问题是 await 自方法之后从未启动任务 GetIntAfterLongWait 返回未启动任务的新实例。所以基本上你有一个僵局,等待一些根本没有开始的事情。

    你可以回来 Task.FromResult(23) 基本上已经完成了任务,或者你可以运行你的任务 Task.Run<int>(() => 23);

        2
  •  4
  •   Thomas    6 年前

    当你返回一个 Task 从非 async 方法?

    Task<T> 一般来说 承诺 对于一个 未来 价值。无论你是否从 异步的 关键字方法或来自另一个源(如启动的线程或IO回调)对调用方不感兴趣,而只是实现策略。这也是为什么接口(或抽象方法定义)没有 异步的 关键字( 异步的 / await 是一种实施策略)。

    您的代码示例

    • 问题1 :你的方法 GetIntAfterLongWait 有两方面的缺陷。第一瞬间 任务 被实例化并卸载到线程中,但结果永远不会被获取(所以永远不会等待……从不拖延任何事情)。
    • 问题2 :第二个任务(返回的任务 GetIntafterLongWait )由(要执行的方法的构造函数)创建,但未启动( Task.Start() )其他更简单的方法是 Task.Run 或者(在这种情况下) Task.FromResult . 任务(或承诺)永远不会传递结果,因为构造函数中的函数块永远不会执行。
    • 问题3 : Main 方法不等待返回任务的结果(通过 等待 Task.Wait() Task.Result .
        3
  •  0
  •   Jesse Johnson    6 年前

    您可能在 GetIntAfterLongWait() 方法。尝试改变 return new Task<int>(() => 23); return Task.FromResult(23); .

    有关的详细信息 Task.FromResult 请参阅上的MSDN文档(带有一个好的示例) How to: Create Pre-Computed Tasks