我正在尝试桥接一些使用期货的现有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()之前的那个。
答案 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()
阻止了。现在存在竞争条件,是线程完成还是处置操作首先执行。
我不建议您如何解决此问题,因为我不知道您要做什么。我只知道您拥有的不可靠。