订阅后台调度程序时,不会调用doOnDispose

时间:2018-10-24 15:49:22

标签: rx-java rx-java2 rx-kotlin

我正在尝试桥接一些使用期货的现有rx代码和api。当我 手动处置一个可观察对象,我希望onDispose()总是被调用。通常可以,但是当我指定自定义调度程序时,有时不会调用它。我的例子:

class Work {

private val disposables = CompositeDisposable()

fun getFuture(): ListenableFuture<String> {

    val future = ResolvableFuture.create<String>()

    disposables.add(

            Observable.fromCallable {
                try {
                    Thread.sleep(2000)
                } catch (ex: InterruptedException) {

                }
                "1"
            }.firstOrError()
                .onErrorReturn { "2" }
                .doOnDispose {
                    println("disposing 1 on ${Thread.currentThread().name}")
                    //sometimes this dispose does not get called
                    future.set("2")
                }
                .subscribeOn(Schedulers.io())
                .doOnDispose {
                    println("disposing 2 on ${Thread.currentThread().name}")
                    //only this dispose gets called every time
                    //future.set("2")
                }
                .subscribe(Consumer {
                    future.set("2")
                })
    )

    return future
}

fun stop() {
    disposables.clear()
}

}

@Test
fun `doOnDispose does not get called`() {
    println("------------")

    for (i in 1..100) {

        val work = Work()

        val future = work.getFuture()

        println("Cancelling")

        work.stop()

        println("Getting ${Thread.currentThread().name}")
        val result = future.get(2, TimeUnit.SECONDS)

        assertEquals("2", result)

        println("------------")
    }
}

发生的事情是每次仅调用第二个onDispose。有时根本不会调用.subscribeOn()之前的那个。

1 个答案:

答案 0 :(得分:0)

您正在这里混合模式。不要那样做使用RxJava或使用Future。您已经创建了维护噩梦的开始。

private async void ScrollViewer_Loaded(object sender, RoutedEventArgs e) { await CargaExcelEnGrid(); } private async Task CargaExcelEnGrid() { try { await vm.LoadDatafromExcel(); //loading in the viewmodel grdExcel.ItemsSource = null; grdExcel.ItemsSource = vm.TableExcel.DefaultView; foreach (CErrorExcel error in vm.ErrorExcel) { DataGridCell cell = GetCell(error.row, error.col, grdExcel); cell.Foreground = new SolidColorBrush(Color.FromRgb(255, 0, 0)); cell.ToolTip = error.Error; } } catch ( Exception err) { ModernDialog.ShowMessage(err.Message, "Error", MessageBoxButton.OK); } } public DataGridCell GetCell(int rowIndex, int columnIndex, DataGrid dg) { DataGridRow row = dg.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow; if (row == null) { dg.UpdateLayout(); dg.ScrollIntoView(dg.Items[rowIndex]); row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(rowIndex); } DataGridCellsPresenter p = GetVisualChild<DataGridCellsPresenter>(row); DataGridCell cell = p.ItemContainerGenerator.ContainerFromIndex(columnIndex) as DataGridCell; return cell; } 调度程序上创建了一个线程,该线程立即休眠2秒。放置观察者链(“放置2”),释放资源,并且io()以其方式返回链。但是,dispose()dispose()线程上不会做任何事情,因为它被io()阻止了。现在存在竞争条件,是线程完成还是处置操作首先执行。

我不建议您如何解决此问题,因为我不知道您要做什么。我只知道您拥有的不可靠。