- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试了解 suspendCoroutine
和 suspendCancellableCoroutine
。我认为它们在以下情况下可能有用:
这可以编译,但永远不会超过“延迟结束”,即继续永远不会恢复:
import kotlinx.coroutines.*
fun main(args: Array<String>) {
println("Hello, world!")
runBlocking {
launch {
postComment()
}
}
}
var isLoggedIn = false
var loginContinuation: CancellableContinuation<Unit>? = null
suspend fun postComment() {
if (!isLoggedIn) {
showLoginForm()
suspendCancellableCoroutine<Unit> {
loginContinuation = it
}
}
// call the api or whatever
delay(1000)
println("comment posted!")
}
suspend fun showLoginForm() {
println("show login form")
// simulate delay while user enters credentials
delay(1000)
println("delay over")
isLoggedIn = true
// resume coroutine on submit
loginContinuation?.resume(Unit) { println("login cancelled") }
}
我已经尝试了我能想到的一切,包括将对 suspendCancellableCoroutine
的调用移到登录检查之外,将 showLoginForm
的内容包装在 withContext( Dispatchers.IO)
,使用 coroutineScope.launch(newSingleThreadContext("MyOwnThread")
等。我从互联网上阅读的印象是,这是一个有效的用例。我是什么做错了吗?
最佳答案
首先,您误解了挂起
函数的概念。调用函数 showLoginForm()
确实不会启动新的协程。单个协程中的代码始终按顺序执行 - 首先调用 showLoginForm()
,它会延迟,不会恢复任何继续,因为 loginContinuation
为 null
code>,然后 suspendCancellableCoroutine
永远挂起你的协程并导致死锁。
启动一个执行 showLoginForm()
的新协程可以使您的代码正常工作:
suspend fun CoroutineScope.postComment() {
if (!isLoggedIn) {
launch {
showLoginForm()
}
suspendCancellableCoroutine<Unit> {
loginContinuation = it
}
}
// call the api or whatever
delay(1000)
println("comment posted!")
}
此代码仍然可能会失败 (*),但在这种特殊情况下不会失败。此代码的工作版本如下所示:
import kotlin.coroutines.*
import kotlinx.coroutines.*
fun main(args: Array<String>) {
println("Hello, world!")
runBlocking {
postComment()
}
}
var isLoggedIn = false
suspend fun CoroutineScope.postComment() {
if (!isLoggedIn) {
suspendCancellableCoroutine<Unit> { continuation ->
launch {
showLoginForm(continuation)
}
}
}
delay(1000)
println("comment posted!")
}
suspend fun showLoginForm(continuation: CancellableContinuation<Unit>) {
println("show login form")
delay(1000)
println("delay over")
isLoggedIn = true
continuation.resume(Unit) { println("login cancelled") }
}
此外,在您的示例中不需要挂起协程。如果我们可以在同一个协程中执行它的代码,为什么我们还需要另一个协程呢?无论如何,我们需要等到它完成。由于协程按顺序执行代码,因此只有在 showLoginForm()
完成后,我们才会转到 if
分支之后的代码:
var isLoggedIn = false
suspend fun postComment() {
if (!isLoggedIn) {
showLoginForm()
}
delay(1000)
println("comment posted!")
}
suspend fun showLoginForm() {
println("show login form")
delay(1000)
println("delay over")
isLoggedIn = true
}
此方法最适合您的示例,其中所有代码都是连续的。
(*) - 如果在 showLoginForm
完成后调用 suspendCancellableCoroutine
,此代码仍然可能导致死锁 - 例如,如果您删除 delay
调用在 showLoginForm
中或者如果您使用多线程调度程序 - 在 JVM 中,不能保证 suspendCancellableCoroutine
会早于 showLoginForm
被调用。此外,loginContinuation 不是 @Volatile,因此使用多线程调度程序,代码也可能因可见性问题而失败 - 执行 showLoginForm 的线程可能会观察到 loginContinuation
为null
。
关于asynchronous - Kotlin 延续未恢复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60278108/
函数式编程中有一个 CPS 技巧,它采用非尾递归函数并以连续传递样式 (CPS) 重写它,从而轻松地使其成为尾递归。很多问题实际上都涵盖了这一点,例如 https://lorgonblog.wordp
这篇文章是这个 post 的延续 我有 DlUser 类,这个类的每个对象都可能有 DLFaceBook 类,DlFaceBook 的每个对象都可以有映射为 myFriends 的 friend 。
我理解 Reader 或 Maybe 或 State monads 是如何工作的,但在 Continuations monad 上遇到了困难。 像下面这样的例子,吹我的头 type Continuat
协程、延续和生成器之间有什么区别? 最佳答案 我将从生成器开始,因为它们是最简单的情况。正如 @zvolkov 提到的,它们是可以重复调用而不返回的函数/对象,但在调用时将返回(产生)一个值,然后挂起
在下面的代码上调用 await RunAsync(); 时,我希望继续运行 TaskContinuationOptions.OnlyRanToCompletion 继续运行,但是 OnlyOnCanc
我正在使用 jetty-7.4.1.v20110513 和 servlet-api-2.5 我尝试在以下 servlet 中使用连缀。 import java.io.*; import java.
我一直在努力解决 scala 延续的复杂打字问题。我一直在阅读我能找到的所有 Material ,包括关于 continuations 包的引用文档。我想我已经在某种程度上弄清楚了,当你考虑它时它是有
我阅读了很多有关 CosmosDB 分页的文档,并认为 token 应该如下所示: {\"token\":\"xxxxxx\",\"range\":{\"min\":\"xxxxxxxxxx\",\"
我阅读了很多有关 CosmosDB 分页的文档,并认为 token 应该如下所示: {\"token\":\"xxxxxx\",\"range\":{\"min\":\"xxxxxxxxxx\",\"
假设您有服务: interface ISuessService { Task Thing1(); Task Thing2(); } 我有一个扩展方法 ContinueOnUIThrea
我在一段文本上成功应用了 white-space: nowrap。我想知道如果文本被 nowrap 样式截断,是否有可能在文本末尾获得标准的“...”。这是 CSS 可以解决的问题吗?还是我需要 ja
我正在尝试使用 Scala (2.9.0) 延续来构建一个看似阻塞的 API,但这实际上是异步的。假设你想写这样的东西: if(ask("Continue?")) //Prompts Yes/No
我正在使用 Jetty 7 延续来实现一些异步处理。我想做的是开始延续(通过 .suspend()),然后将延续交给其他一些将组成响应的对象,这样效果很好。但是 Jetty 不断将响应(isIniti
协程、延续和生成器之间有什么区别? 最佳答案 我将从生成器开始,因为它们是最简单的情况。正如@zvolkov 提到的,它们是可以重复调用而不返回的函数/对象,但是在调用时将返回(产生)一个值,然后暂停
C++ 11 std::future lacks then 方法将延续附加到 future 。 Boost boost::future provides这个,还有一个example (我无法运行) 我
我在使用 Azure Cosmos DB(通过 .NET SDK)时发现了一些奇怪的东西。 通常,当我使用延续 token 逐页请求查询时,我永远不会获得在创建第一个延续 token 之后创建的文档。
我目前正在实现 System.Web.Http.IActionFilter它调用内部服务来确定当前请求是否可以继续。我遇到的问题是返回 Task基于由 Task 封装的一段逻辑. 一个例子可能会有所帮
我想要一个可序列化的延续,这样我就可以在等待新事件的同时将异步工作流程 pickle 到磁盘。当异步工作流等待 let! 时,它将与唤醒它所需的记录一起保存。而不是内存中的任意 IAsyncResul
我正在努力理解 Continuations 的概念(如 Seaside with Smalltalk 中所使用的)。维基百科的一个片段说: "... refer to first-class cont
我有一个 servlet 过滤器,它充当我的 Web 堆栈的基础。在我的 web.xml 中我有指定我希望过滤器也充当 FORWARD 调度程序。 MyFilter /*
我是一名优秀的程序员,十分优秀!