更正:从以下两个答案中可以看出,问题看起来特定于 dart ,因为C#实现了Task.Wait
,可以实现所需的效果。如果有任何关于为什么在飞镖中无法实现这一目标或如何在那里实现它的原因,我将不胜感激。我很乐意以目前的形式结束这个问题。
在某些情况下,让同步函数在传递结果之前在内部等待完成的异步调用是有意义的。 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");
}
}
问题:为什么不允许这样做?
答案 0 :(得分:4)
这是一个设计选择。 Dart是单线程的 - 每个同步函数调用将在允许任何其他代码运行之前运行完成。如果允许同步函数阻塞直到将来完成,那么将不会运行其他代码,并且将来永远不会完成(因为完成它的代码无法运行)。
可以有一个系统允许其他代码在一个同步功能被阻止时运行。这需要具有多个活动堆栈(并行或不并行),或者隐式转换整个程序为异步。当你编译成JavaScript时,这两个选择都不是很好,所以Dart并没有尝试这样做。
答案 1 :(得分:3)
await
是异步等待,因此将它放在同步函数中没有意义。要异步,方法需要在等待操作启动时返回,而同步方法需要运行完成。
您可以使用同步等待,在这种情况下,您的方法不需要async
。在C#中,您可以通过在返回的任务上调用Wait()
方法来完成此操作。
答案 2 :(得分:2)
因为等待和回归未来是根本不同的。
返回一个将来释放当前线程并可选择为稍后调度一个延续,等待阻塞当前线程。
例如,在UI线程中,返回一个未来很好,但是等待会导致UI挂起,在Web服务器中线程等待会阻塞线程并阻止Web服务器处理更多请求等。
甚至可能等待异步操作会导致死锁。
.net提供Task.Wait,当你知道等待没问题的时候,我不知道dart - 但这不是自动的(除了等待C#中异步方法中的catch子句内部)
答案 3 :(得分:0)
在Dart标记中,函数/方法async
告诉VM它需要在执行代码之前重写代码。
await
不会将异步函数更改为同步函数,该函数仍然是异步的,它只允许比then(() { return ...then(() { return...})})
链更好的语法。
如果您进行异步调用,以下所有内容都是异步的,那么您无能为力。