我在WinForms应用程序中使用RxFramework。我试图运行一个Observable异步,并在用户单击按钮时使用CancellationDisposable取消操作。但它不起作用!
假设我有一个带有2个按钮和一个ProgressBar的窗体。 Button1_click在新线程上订阅观察者。然后在紧后按下Button2_click取消操作。
为什么 cancel.Token.IsCancellationRequested 从来都不是真的?
private IDisposable obs = null;
private void button1_Click(object sender, EventArgs e) {
var countObserver = Observable.Create<int>(observer => {
var cancel = new CancellationDisposable();
if (!cancel.Token.IsCancellationRequested) {
//Step 1 of a long running process using lot of resources...
observer.OnNext(1);
}
if (!cancel.Token.IsCancellationRequested) {
//Step 2 of a long running process using lot of resources...
observer.OnNext(1);
}
if (!cancel.Token.IsCancellationRequested) {
//Step 3 of a long running process using lot of resources...
observer.OnNext(1);
}
observer.OnCompleted();
return cancel;
});
obs = countObserver
.ObserveOn(new ControlScheduler(this))
.SubscribeOn(Scheduler.ThreadPool)
.Subscribe(i => {
//Update a progress bar here...
});
}
private void button2_Click(object sender, EventArgs e) {
if (obs != null)
obs.Dispose();
}
最佳答案
发生这种情况是因为传递给Observable.Create
的lambda直到经过所有步骤后才返回CancellationDisposable
。因此,操作顺序如下:Subscribe
ThreadPool
线程上,执行进入lambda CancellationDisposable
已创建cancel
obs
获得其值Button2
并调用obs.Dispose
cancel
获取cancel.Token.IsCancellationRequested=true
。但是什么都没有发生,因为一切都已经发生了。
这是固定代码:private void button1_Click(object sender, EventArgs e) {
var countObserver = Observable.Create<int>(observer => {
var cancel = new CancellationDisposable();
// Here's the magic: schedule the job in background and return quickly
var scheduledItem = Scheduler.ThreadPool.Schedule(() =>
{
if (!cancel.Token.IsCancellationRequested) {
//Step 1 of a long running process using lot of resources...
observer.OnNext(1);
}
if (!cancel.Token.IsCancellationRequested) {
//Step 2 of a long running process using lot of resources...
observer.OnNext(1);
}
if (!cancel.Token.IsCancellationRequested) {
//Step 3 of a long running process using lot of resources...
observer.OnNext(1);
}
observer.OnCompleted();
});
return new CompositeDisposable(cancel, scheduledItem);
});
obs = countObserver
.ObserveOn(new ControlScheduler(this))
.Subscribe(i => {
//Update a progress bar here...
});
}