async
is built on the notion of an asynchronous operation, with a definite beginning and ending. At the end, there may be a single result. That's it. Note that async
methods may not have out
parameters because they don't fit into this model.
If you want a stream of values, then use Reactive Extensions. There's an interesting RxUI library that nicely marries observables with MVVM patterns.
That said, I don't think either of your examples actually require observables (though you certainly could move to Rx if you wanted). I address your first example (data-bound async
properties) on my blog; the short answer is to use a wrapper for Task<T>
that implements INotifyPropertyChanged
like this one:
// Service
public async Task<ImageSource> GetImage(object key, CancellationToken cancellationToken);
// ViewModel
INotifyTaskCompletion<ImageSource> Image { get; private set; }
...
Image = NotifyTaskCompletion.Create(GetImage(key, token));
// View
<Image Source="{Binding Image.Result}" />
Regarding your second example, this can be done fairly easily by treating the new items as progress updates from the async
method:
// Service
public async Task<int> GetImages(object queryParemeters,
CancellationToken cancellationToken,
IProgress<CustomFileInfoType> progress);
// ViewModel
var collection = new ObservableCollection<CustomFileInfoType>();
var progress = new Progress<CustomFileInfoType>(x => collection.Add(x));
await GetImages(query, token, progress);
Exposing these types is something else completely. WinRT components must expose WinRT types. I recommend you write the basic logic (service and possibly ViewModel) using pure async
/await
and then do the translation separately. As you noted, AsyncInfo.Run
will translate Task
to IAsyncOperation
, and there isn't a built-in translator for ObservableCollection
to IObservableVector
(though it isn't hard to write, and there are several available via Google).
Then also - how would I do all this in C++/CX? Or JS?
I have no idea on that one. You'll probably have to write your own equivalent for NotifyTaskCompletion
on those platforms, or just use callbacks.