为什么这个 CancellationDisposable 永远不会在 Observable.Dispose() 上被取消?
我在 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();
}
Im using RxFramework within an WinForms app. Im trying to run an Observable async and using the CancellationDisposable to cancel the operation when user clicks a button. but it is not working!
Suppose I have a form with 2 buttons and a ProgressBar. Button1_click subscribe to the observer on a new Thread. Button2_click is then pressed right after to cancel the operation.
Why cancel.Token.IsCancellationRequested is never true?
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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
之所以会发生这种情况,是因为您传递给
Observable.Create
的 lambda 不会返回CancellationDisposable
直到它完成所有步骤。因此,操作的顺序如下:Subscribe
ThreadPool
线程上,执行进入CancellationDisposable
cancel
从 lambdaobs
获取其值Button2
并调用obs.Dispose
cancel
获取cancel.Token.IsCancellationRequested=true
。但什么也没有发生,因为一切都已经发生了。这是固定代码:
It happens so because the lambda you pass to
Observable.Create
does not return theCancellationDisposable
until it goes through all the steps. So, the order of actions is the following:Subscribe
ThreadPool
thread, the execution enters the lambdaCancellationDisposable
is createdcancel
is returned from lambdaobs
gets its valueButton2
and callobs.Dispose
cancel
getscancel.Token.IsCancellationRequested=true
. But nothing happens since everything has already happened.Here's the fixed code:
相反,上面的代码存在许多错误,但实际上有一种更好的方法来完成此操作(警告:前面在 TextArea 中编码):
How about this instead, there are a number of bugs with the code above, but there's actually a better way to do this altogether (Warning: Coding in TextArea ahead):