Reputation: 12898
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?
Upvotes: 2
Views: 1719
Reputation: 29786
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.
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.
Upvotes: 8