Back to the initial question, yes, it is correct to patch it like that and you can be sure that the
FileStream will be disposed of. Managing the lifetime of resources (like a file stream) was the main reason we came up with the idea of a resource provider. Your example shows nicely howto tie the lifetime of such a resource to an observable with the
Using (Provider) [Observable] region. I should however mention that you could’ve skipped the resource provider entirely in this example with the
Using [Observable] region.
async/await in VL. Yes, please open a quest in the VL-Language repository. For example introducing
Await as a node shouldn’t be too hard, we can indeed rely on the C# compiler doing the heavy lifting, but the implications of such a feature are quite vast.
@sebl no, it does not block. Even though the patches inside the
Using regions are executed on the main thread (the moment the
HoldLatest node subscribes), the resulting serialization task wrapped in an observable will complete at a later time. The serialization will probably (not necessarily, depends on the library) run on a different thread. Once it completes, the used file stream will be disposed of.
I’d not recommend using the
AsyncTask region and waiting on the result inside as a replacement:
- It creates two tasks, one doing the actual work, the other just waiting on it and blocking the thread executing it.
- It could be that the async method being called is thread affine (for example expects to be called on the UI thread having a message pump) - in that case the whole thing would not work at all and probably crash.
Provider was indeed our invention, tackling the problem of managing the lifetime of a resource, especially when resources depend on each other and/or many consumers need it.
In the grander scheme of things like tasks and observables - well from a theoretical perspective they could all be seen as monads
(return = FromResult, bind = ContinueWith)
(return = Return, bind = SelectMany)
(return = Return, bind = Bind)
allowing you to chain computations. Equipped with some operators (like
Using (Provider) or
ToObservable [Task]) you can even combine them as seen in this example. Note however that not all directions necessarily make sense. For example I’d have no clue what an operator going from
Provider<U> would accomplish or even how to implement it without blocking the calling thread.