【问题标题】:Why 'await' cannot be used in ordinary functions?为什么'await'不能在普通函数中使用?
【发布时间】:2015-10-27 21:46:59
【问题描述】:

更正:从两个答案来看,问题看起来是 dart 特有的,因为 C# 实现 Task.Wait 允许达到预期的效果。我将不胜感激任何进一步的信息,说明为什么这在 dart 中不可能或如何在那里实现它。我很乐意以目前的形式结束这个问题。


在某些情况下,让同步函数在内部使用异步调用等待它们完成后再传递结果是有意义的。这在 C#Dart 中都是明确不允许的:任何使用 await 的东西都必须标记为 async(因此返回一个未来)。

Dart 中的

一个简单的例子,但同样适用于 C#

免责声明:这不是我做事的方式,所以不建议将所有方法转换为异步的“正确”解决方案;这里的代码只是为了说明这个问题。

我有一个通用包装器的完全异步实现,用于对某些特定 REST API 的 HTTP 请求。它会进行一些登录、身份验证等操作:

class RequestProcessor {
     Future post(String path, [payload]) async {
          return request("POST", path, payload);
     }
}

我想实现一个面向用户的高级 API,将请求转换为 REST-API。其中一些方法我希望同步。这是我想要但不允许拥有的:

class API {
    final RequestProcessor processor;

    API(this.processor);

    // this takes long and should be asynchronous, happy with a future (OK)
    Future getQueryResults(query) async {
        return await processor.post("/query", query);
    }

    // here I would prefer to have it synchronous (COMPILE ERROR)
    String getVersion() {
        return await processor.post("/version");
    }
}

问题:为什么不允许这样做?

【问题讨论】:

标签: asynchronous dart async-await


【解决方案1】:

这是一种设计选择。 Dart 是单线程的 - 每个同步函数调用将在允许任何其他代码运行之前运行完成。如果您允许同步函数阻塞,直到未来完成,则不会运行其他代码并且未来将永远不会完成(因为将完成它的代码无法运行)。

可能有一个系统允许其他代码在一个同步功能被阻止时运行。这需要有多个活动堆栈(并行或不并行),或者将整个程序隐式转换为异步。当你编译成 JavaScript 时,这两种选择都不是很好,所以 Dart 没有尝试这样做。

【讨论】:

  • 阻塞的故事很清楚:同步调用阻塞。所以重点是真正的单线程,这就是它与提供同步等待的 C# 的不同之处?
  • 是的,C#已经是多线程的了,所以阻塞一个线程不是问题。 Dart 是单线程的(当它编译成 JavaScript 时必然是单线程的),所以它不能在不阻塞整个隔离的情况下阻塞一个线程。
【解决方案2】:

await 是一个异步等待,因此将它放在同步函数中是没有意义的。要异步,方法需要在等待的操作启动时返回,而同步方法需要运行完成。

您可以改用同步等待,在这种情况下,您的方法不需要是async。在 C# 中,您可以通过在返回的任务上调用 Wait() 方法来做到这一点。

【讨论】:

  • 在c#中你可以调用Wait()做等待任务完成,也许dart中有类似的东西。
  • dart 中似乎没有类似的机制,但它让我意识到我不知道 C# 的特定细节。谢谢。
【解决方案3】:

因为等待和返回未来是根本不同的。

返回一个future会释放当前线程,并且可以选择为以后安排一个继续,等待阻塞当前线程。

例如,在 UI 线程中,返回 future 是可以的,但等待会导致 UI 挂起,在 Web 服务器线程中,等待会阻塞线程并阻止 Web 服务器处理更多请求等。

甚至有可能等待异步操作会导致死锁。

.net 提供 Task.Wait,当你知道等待很好时,我不知道 dart - 但这不是自动的(C# 中异步方法中的 catch 子句中的 await 除外)

【讨论】:

  • 我非常了解 await 背后的原因,所以这不是我的问题。一般来说,它看起来归结为“为什么 dart 没有 C# Wait() 的类似物或如何实现这一点”......
【解决方案4】:

在 Dart 中标记函数/方法async 告诉 VM 在执行之前需要重写代码。 await 不会将异步函数更改为同步函数,该函数仍然是异步的,它只是允许比 then(() { return ...then(() { return...})}) 链更好的语法。

如果您进行异步调用,那么后面的所有内容都是异步的,那么您将无能为力。

【讨论】:

  • 我认为他的问题是为什么等价物在 C# 中不起作用。
  • 因为异步和非异步方法有本质上不同的语义。异步方法被转换为状态机,它允许在异步方法完成后“恢复”代码(不是最好的词)。
猜你喜欢
  • 1970-01-01
  • 2023-01-17
  • 2020-10-04
  • 1970-01-01
  • 2017-08-24
  • 2013-08-16
  • 2022-01-21
  • 2020-03-05
相关资源
最近更新 更多