Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在Observable.Dispose()上从未取消此CancellationDisposable?_C#_.net_Windows_System.reactive - Fatal编程技术网

C# 为什么在Observable.Dispose()上从未取消此CancellationDisposable?

C# 为什么在Observable.Dispose()上从未取消此CancellationDisposable?,c#,.net,windows,system.reactive,C#,.net,Windows,System.reactive,Im在WinForms应用程序中使用RXFramew。我试图运行一个可观察的异步,并在用户单击按钮时使用CancellationDisposable来取消操作。但它不起作用 假设我有一个有两个按钮和一个进度条的表单。按钮1\u单击订阅新线程上的观察者。按钮2\u单击后立即按下以取消操作。 为什么cancel.Token.IsCancellationRequested从来都不是真的 private IDisposable obs = null; private void button1_Click

Im在WinForms应用程序中使用RXFramew。我试图运行一个可观察的异步,并在用户单击按钮时使用CancellationDisposable来取消操作。但它不起作用

假设我有一个有两个按钮和一个进度条的表单。按钮1\u单击订阅新线程上的观察者。按钮2\u单击后立即按下以取消操作。 为什么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();
}
private-IDisposable obs=null;
私有无效按钮1\u单击(对象发送者,事件参数e){
var countObserver=Observable.Create(observator=>{
var cancel=new CancellationDisposable();
如果(!cancel.Token.IsCancellationRequested){
//使用大量资源的长时间运行流程的步骤1。。。
OnNext观察员(1);
}
如果(!cancel.Token.IsCancellationRequested){
//使用大量资源的长时间运行流程的步骤2。。。
OnNext观察员(1);
}
如果(!cancel.Token.IsCancellationRequested){
//使用大量资源的长时间运行流程的步骤3。。。
OnNext观察员(1);
}
observer.OnCompleted();
返回取消;
});
obs=可计数观察者
.ObserveOn(新的ControlScheduler(此))
.SubscribeOn(Scheduler.ThreadPool)
.订阅(i=>{
//在此处更新进度条。。。
});
}
私有无效按钮2\u单击(对象发送者,事件参数e){
如果(obs!=null)
obs.Dispose();
}

相反,上面的代码有很多错误,但实际上有一个更好的方法可以做到这一点(警告:在前面的TextArea中编码):

countObservable=Observable.Timer(新的ControlScheduler(this));
var buttonObservable=Observable.FromEventPattern(
x=>button1.点击+=x,x=>button1.点击-=x);
可数可观测
.TakeUntil(按钮不可维修)
.订阅(x=>/*做一些事情*/);

之所以会出现这种情况,是因为传递给
的lambda是可观察的。Create
不会返回
CancellationDisposable
,直到它完成所有步骤。因此,行动顺序如下:

  • 您可以调用
    Subscribe
  • UI线程块
  • ThreadPool
    线程上,执行进入lambda
  • 取消一次性
    已创建
  • 您多次检查取消并执行整个过程。在此期间,将更新进度条
  • cancel
    从lambda返回
  • UI线程被释放,
    obs
    获取其值
  • 单击
    按钮2
    并调用
    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...
        });
    
    }
    
    private void按钮1\u单击(对象发送者,事件参数e){
    var countObserver=Observable.Create(observator=>{
    var cancel=new CancellationDisposable();
    //神奇之处在于:在后台安排工作并快速返回
    var scheduledItem=Scheduler.ThreadPool.Schedule(()=>
    {
    如果(!cancel.Token.IsCancellationRequested){
    //使用大量资源的长时间运行流程的步骤1。。。
    OnNext观察员(1);
    }
    如果(!cancel.Token.IsCancellationRequested){
    //使用大量资源的长时间运行流程的步骤2。。。
    OnNext观察员(1);
    }
    如果(!cancel.Token.IsCancellationRequested){
    //使用大量资源的长时间运行流程的步骤3。。。
    OnNext观察员(1);
    }
    observer.OnCompleted();
    });
    返回新的CompositeDisposable(取消,scheduledItem);
    });
    obs=可计数观察者
    .ObserveOn(新的ControlScheduler(此))
    .订阅(i=>{
    //在此处更新进度条。。。
    });
    }
    
    此解决方案对于上面的示例非常有效,我有一个简单的计数器(我想我给出了一个不好的示例),但问题是当我有一个非常长的运行过程,我在使用数据库和服务,我需要在进入下一步之前进行检查。。。我将更改上面的示例…如果提前处理可观察对象,是否应调用OnCompleted?《处方指南》在这里说了什么?@BentRasmussen我不确定,但我想他们什么也没说。这取决于你决定你的可观察序列何时结束。如果取消时不调用
    OnCompleted
    ,则不会结束。根据您的具体任务,它可能是好的,也可能是坏的。就我个人而言,我倾向于认为它应该在这种情况下结束,也许有一个特殊的标志来区分成功完成和取消完成。
    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...
        });
    
    }