简体   繁体   中英

Observable.Using( ) cancellation

I have a observable made by the Using helper:

var o = Observable.Using(
 () => { 
          return new MyResource 
       },
 res => {
          return new Observable.Create<string>(observer => ....);
        });

How can I cancel the observable? And by that make sure MyResource is disposed of?

I see there are a Observable.Using( ) that includes a cancellationToken , but signature is so different, that I'm not able to make it work...

Update: As James points out, by disposing the observable, my resource will be disposed as well. In my case, a plain disposal is not enough. I need to call a method on the resource first. How can that be archived?

You don't need to clean up an observable - just the subscription. Simply call Dispose on the handle returned from Subscribe when you make a subscription to cancel it.

The resource created by the factory delegate supplied as the first argument to Using has a lifetime governed by lifetime of subscriptions to the observable created by Using .

Here's an example:

var xs = Observable.Using(
    () => {                        
        var resource =  Disposable.Create(() => Console.WriteLine("Binned"));
        Console.WriteLine("Created");
        return resource;
    },
    res => Observable.Never<Unit>());

Console.WriteLine("Subscribing");
var sub1 = xs.Subscribe();
var sub2 = xs.Subscribe();
Console.WriteLine("Disposing");            
sub1.Dispose();

Gives output:

Subscribing
Created
Created
Disposing
Binned

Since sub2 never finishes and isn't disposed, there is only a single Binned message displayed.

In this example, sub1 completes immediately and there is no cancellation:

var xs = Observable.Using(
    () => {                        
        var resource =  Disposable.Create(() => Console.WriteLine("Binned"));
        Console.WriteLine("Created");
        return resource;
    },
    res => Observable.Return(1));

Console.WriteLine("Subscribing");
var sub1 = xs.Subscribe();

This time the resource is still cleaned up, because the subscription terminated normally:

Subscribing
Created
Binned

The purpose of the overload of Using sporting cancellation tokens is to allow you to cancel asynchronous creation of the resource and the dependent observable. The cancellation tokens are signalled on disposal of subscription handles - of course this scenario is only really going to be useful if you have relatively lengthy creation times and early disposal is likely.

Addendum

To address the corollary to your question:

...a plain disposal is not enough. I need to call a method on the resource first. How can that be [achieved]?

From your resource factory method (the first argument to using), do this:

var xs = Observable.Using(
    () =>
    {                        
        var processHandle = /* code to create process */
        return Disposable.Create(() => /* code to kill process using processHandle */;
    },
    // Rest of code...

Disposable.Create is a helper method you can use that accepts in Action that's invoked upon disposal.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM