- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已阅读 article .
有两种方法可以使计算代码可取消。第一个是定期调用检查取消的挂起函数。有一个 yield 函数是一个很好的选择。另一种是显式检查取消状态。
我知道 Flow 正在暂停功能。
我运行代码 B,并按预期获得结果 B。
我认为我不能使计算代码 A 可取消,但实际上我可以在单击“开始”按钮发出流后单击“停止”按钮取消流,为什么?
代码A
class HandleMeter: ViewModel() {
var currentInfo by mutableStateOf(2.0)
private var myJob: Job?=null
private fun soundDbFlow() = flow {
while (true) {
val data = (0..1000).random().toDouble()
emit(data)
}
}
fun calCurrentAsynNew() {
myJob?.cancel()
myJob = viewModelScope.launch(Dispatchers.IO) {
soundDbFlow().collect {currentInfo=it }
}
}
fun cancelJob(){
myJob?.cancel()
}
}
@Composable
fun Greeting(handleMeter: HandleMeter) {
var currentInfo = handleMeter.currentInfo
Column(
modifier = Modifier.fillMaxSize(),
) {
Text(text = "Current ${currentInfo}")
Button(
onClick = { handleMeter.calCurrentAsynNew() }
) {
Text("Start")
}
Button(
onClick = { handleMeter.cancelJob() }
) {
Text("Stop")
}
}
}
代码 B
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch(Dispatchers.IO) {
cal()
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin()
println("main: Now I can quit.")
}
suspend fun cal() {
val startTime = System.currentTimeMillis()
var nextPrintTime = startTime
var i = 0
while (i < 5) {
if ( System.currentTimeMillis() >= nextPrintTime) {
println("job: I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
结果 B
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
main: I'm tired of waiting!
job: I'm sleeping 3 ...
job: I'm sleeping 4 ...
main: Now I can quit.
添加内容:
致 Tenfour04:谢谢!
如果你说的以下内容是真实的。我认为代码C可以在系统一次完成操作doBigBlockingCalculation()
时取消,对吧?为什么我需要代码 D?
由于 emit() 是一个挂起函数,您的 Flow 能够在下一次在该 while 循环中调用 emit() 函数时中断并结束协程。
代码 C
private fun complicatedFlow() = flow {
while (true) {
val data = (0..1_000_000).doBigBlockingCalculation()
emit(data)
}
}.flowOn(Dispatchers.Default) // since the calculation is blocking
代码 D
private fun complicatedFlow() = flow {
while (true) {
val data = (0..1_000_000)
.chunked(100_000)
.flatMap {
it.doBigBlockingCalculation().also { yield() }
}
emit(data)
}
}.flowOn(Dispatchers.Default) // since the calculation is blocking
最佳答案
流本身是冷的。它是一些挂起函数的包装器,当在 Flow 上调用 collect()
或其他一些终端挂起函数时,这些挂起函数将运行。
在您的代码 A 中,当作业被取消时,它正在取消在流程上调用 collect
的协程。 collect
是一个挂起函数,因此取消将传播到您在 soundDbFlow()
中定义的函数。由于 emit()
是一个挂起函数,您的 Flow 能够在下次在该 while 循环中调用 emit()
函数时中断并结束协程。
以下是您如何使用这些知识的示例:
假设您的函数必须像这样进行很长的计算:
private fun complicatedFlow() = flow {
while (true) {
val data = (0..1_000_000).doBigBlockingCalculation()
emit(data)
}
}.flowOn(Dispatchers.Default) // since the calculation is blocking
现在如果你试图取消这个流程,它会起作用,但是由于 data
行是一个非常慢的操作,没有暂停,流程仍然会无缘无故地完成这个很长的计算,消耗资源的时间超过必要的时间。
要解决此问题,您可以通过 yield()
调用将您的计算分成更小的部分。然后可以更迅速地取消流程。
private fun complicatedFlow() = flow {
while (true) {
val data = (0..1_000_000)
.chunked(100_000)
.flatMap {
it.doBigBlockingCalculation().also { yield() }
}
emit(data)
}
}.flowOn(Dispatchers.Default) // since the calculation is blocking
不是一个完美的例子。将一个大的 IntRange 分块有点浪费。 IntRange 几乎不占用任何内存,但分块将其转换为包含范围内每个值的列表。
关于kotlin - 为什么我可以在不调用 yield 或确定 Kotlin 中的 isActive() 标识的情况下取消流程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70956455/
我有一个用户表,由活跃用户的 boolean 值组成,如下表所示 id | name | active 1 | john | false 2 | bob | true 3 | jeff | t
我想我明白为什么作为参数传递给箭头函数的第一个 isActive 实例被封装在大括号中,即 { isActive },而第二个isActive 没有封装在大括号中,但我想确保我理解正确。 封装在大括号
这个问题已经有答案了: What is the difference between public, protected, package-private and private in Java? (
与Should I delete or disable a row in a relational database?略有相关 考虑到我将采用在历史表中对我的表进行仓储更改的策略,我面临以下用于在 M
在新版本的iOS和Xcode中 NavigationLink(isActive: , destination: , label: ) 已弃用。 那我们如何控制NavigationLink的状态呢? 最
我正在编写一个小型 UWP 项目,也使用 MVVM 模式(MVVM Light 框架)进行学习,并且在许多场景和控件中遇到了绑定(bind)问题。 我已经努力将其中一个隔离到可用的迷你示例项目中 he
我发现XCode Organizer崩溃报告有很多崩溃。 Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_INVAL
我目前正在考虑QTimer 实现的线程安全问题。 在我的应用程序中,我使用 bool isActive() 方法来检查计时器是否正在运行。由于我计划在其他线程中也使用此方法,因此我的想法转向了线程安全
我有路线 例如,当我在页面/catalog/10 时,我会尝试检查该路由是否处于事件状态 this.context.router.isActive('/catalog/:category') 但我总
我已经开始学习 SwiftUI,但是在构建我的 NavigationView 时遇到了一些问题 - 我不确定这是否是一个错误,或者我是否误解了嵌套导航链接应该如何工作! 这是我当前的代码: impor
我有一个 Bootstrap 实现,其中导航栏是一个无序列表,每个项目都设置为在事件时突出显示。突出显示本身使用 CSS 设置样式,但使用 AngularJS 检查事件状态: B
我使用 es6、twitter bootstrap 和 react-router 1.0.0-rc3。我想创建一个导航栏并添加到 li 元素类 active。 我尝试使用 history 的 isAc
相关bootstrap.js代码: ... Dropdown.prototype = { constructor: Dropdown , toggle: function (e) {
在 wxGTK 下,事件窗口没有从 IsActive() 返回真值。 我的软件有一个主窗口和一组工具窗口,都是从wxFrame派生出来的。当主窗口移动时,它会捕获移动事件并在所有工具窗口中调用位置方法
我发现只要次要路由打开,router.isActive 就会返回 false。 router.isActive 适合检查“我在路线 (x) 上吗?”(例如:支付页面)——不管哈希状态、查询参数如何和次
我从 UIKit 转到 SwiftUI,我遇到了 NavigationLink 在呈现新 View 时没有动画的问题。 当以下属性为非零时,我已将 View 结构设置为包含 NavigationLin
我正在尝试使用 Router.isActive 检查路由 如果当前路径是/animals/edit (router.isActive('/animals/edit') 是真的。 但是如果当前路线是/a
我正在尝试使用 Kotlin 协程而不是传统的 Java 线程来执行后台操作: 我从中学到了link而且效果很好 val job = launch { for(file in files) {
我正在尝试以编程方式将当前 View 更改为其他 View ,但是 NavigationLink 的 isActive 属性不起作用,我想我忘记了什么。 struct MainView: View {
我有一个 scrollView,我要在其中添加一个 textView。我想将 TextView 置于 schollView 的中心。代码在 textView.centerXAnchor.constra
我是一名优秀的程序员,十分优秀!