CancellationDisposable

CancellationDisposable

我在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
  • UI线程块
  • ThreadPool线程上,执行进入lambda
  • CancellationDisposable已创建
  • 您需要多次检查取消并执行整个过程。在此期间,您的进度栏将更新。
  • 从lambda 返回
  • cancel
  • UI线程被释放,并且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...
        });
    
    }
    

    10-08 14:06