我在一个WinForms应用程序中使用RxFramework。 我试图运行Observableasynchronous,并使用CancellationDisposable取消操作时,用户单击button。 但它不工作!
假设我有一个带有2个button和一个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
从lambda返回 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... }); }
但是,如果这样做的话,上面的代码有一些错误,但是实际上有更好的方法来完成这个工作(警告:TextArea提前编码):
countObservable = Observable.Timer(new ControlScheduler(this)); var buttonObservable = Observable.FromEventPattern<EventArgs>( x => button1.Click += x, x => button1.Click -= x); countObservable .TakeUntil(buttonObservable) .Subscribe(x => /* Do stuff */);