代码之家  ›  专栏  ›  技术社区  ›  Matt W

在这里等什么?

  •  1
  • Matt W  · 技术社区  · 5 年前

    给定方法签名:

    (awaitable) Task<Token> ITokenService.GetAPIToken();
    

    在这个方法中,在线上发生了什么 await ?

    public async Task<User> GetUser(string userId)
    {
        Token token = await TokenService.GetAPIToken();
    
        //..........
    }
    

    我的理解: GetAPIToken 调用当前方法( GetUser 返回一个 Task<User> 对象(哪些) 提供一个 User 对象之后)。当前方法的执行只继续一次 盖特皮托肯 方法返回。

    如果我错了,它的类型/值是什么 token 当代码等待 GetAPIToken() 返回方法?

    我理解调用此方法的结果将不同,因为可以使用或不使用 等待 关键字。请假设,对于该职位,该职位正在与 等待 .

    2 回复  |  直到 5 年前
        1
  •  1
  •   J.P.    5 年前

    在线 await 实际上是执行 GetUser() 停止(等待)直到 GetAPIToken() 返回。这是正确的。因此 token 没有值(在本例中甚至是声明的值),直到它从 GETAPITOKN() 返回。

    什么 GETUSER() 返回取决于调用的方式,有或没有 等待 操作员。如果被调用 等待 的呼叫者 GETUSER() 也会等它完成。在这种情况下,呼叫方最终将获得 User 返回的 GETUSER() 不是 Task<User> .

    在这种情况下,并行运行任何东西都不会使您受益。

    如果在另一方面 GETUSER() 在没有 等待 操作员,有两种情况发生得不同: GETUSER() 当它实际打到您的电话线时,它会返回到较早的呼叫者;并且它会返回一个 任务<用户> 而不是 用户 直接——毕竟还没有创建。

    由此 Task 调用方可以稍后(在并行执行其他操作之后,这将是整个要点)获得结果 用户 . 这可以用不同的方式完成;请参见 Task<> .

    了解事物并行运行的时间是很重要的。在这种情况下(如果 GETUSER() 在没有电话的情况下 等待 )有可能 GETUSER() 返回并继续执行任务,同时在另一个线程中并行执行, GETAPITOKN() 还没有回来,所以 令牌 未初始化。

    用图表查看这篇不错的msdn文章: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/index#BKMK_WhatHappensUnderstandinganAsyncMethod

        2
  •  7
  •   Eric Lippert    5 年前

    我的理解: GetAPIToken 调用当前方法( GetUser 返回一个 Task<User> 对象(稍后将提供用户对象)。当前方法的执行只继续一次 盖特皮托肯 方法返回。

    非常接近。让我们用两种方法把它变脆。

    首先,让我们区分 收益率 --也就是说,将控制权返回给调用方-- 完成 这意味着该方法所代表的任务已经完成,我们要么有它的值,要么在异常完成的情况下有异常。

    在非异步方法中,我们不需要进行区分,因为将控制权返回给调用方只在完成时发生。在异步方法中,我们可以作为挂起(因为等待一个未完成的任务)返回给调用者,或者作为完成返回(当表示的任务被指示为完成时)。

    第二,如果任务在创建时完成了,那么就可以根据所发生的情况来表示工作流;例如,在缓存的情况下,这种情况可能会发生。

    现在,让我们重新陈述一下你对这一点的理解:

    • 盖特皮托肯 调用并将任务返回给当前用户。
    • 如果任务已完成,则在它完成所有工作后返回getapitoken。getuser从已完成的任务中提取令牌,然后继续而不挂起。
    • 如果任务未完成,并且这是getuser中的第一个等待,则getuser将创建一个 任务<用户>
    • 获取用户 分配的剩余部分 获取用户 作为 Task<Token> ,并通过返回 任务<用户>
    • 任务标记 完成后,运行其继续,继续 获取用户 在它停止的地方。

    当代码等待getapitoken()方法返回时,token的类型/值是什么?

    那么,它的价值是多少 token 是否处于等效的非异步情况下?考虑:

    Token x = Foo();
    

    当我们等待foo完成时,x的值是多少?使foo async不起作用;在调用之后才为本地分配值 正常完成 . 如果foo进入无限循环,或者foo抛出,那么 x 从未分配。

    当然,在实践中,C在创建所有局部变量时为其指定默认值,因此这是变量中的值。