Pattern for an async method that returns something immediately
async-await, c#, c++-cx, windows-runtime, winrt-component
Solution
`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.
Problem
If I write a simple function I can get a result immediately. If I use `async/await` and return a `Task` - the method will kinda return when it's done with the task, but what if I need to write a method that needs to return immediately, but then continue updating the result and potentially eventually complete the task? Also what if I want to expose it outside a WinRT Component library for consumption in components in other languages? How would I do it in C# and how would I do it in C++/CX? Or JS perhaps? Example 1: I want to expose a property that returns an `ImageSource` so I can immediately bind it from my MVVM view model to the XAML view. The method to load the `ImageSource` is going to be in a separate class that is exposed outside a WinRT Component (it is a public method). Now I want that method to be awaitable, or at least somehow return a task I can await but also immediately return the `ImageSource` so the property I call it from can immediately return since properties can't be async. The caller doesn't know what type the `ImageSource` will be so it cannot instantiate it since `ImageSource` is virtually an abstract type and is typically represented as a `BitmapImage` or `WriteableBitmap` and in my case both can be returned from the method. Obviously the method itself immediately knows whether it is going to return either of the types of objects, but it takes some time to read/create and or decode the image. I'm thinking the signature might be something like this in C# ``` public async Task<ImageSource> GetImage( object key, out ImageSource bitmap, CancellationToken cancellationToken) ``` and I would simply not await the result of the method in the property accessor, but I'm thinking I'll be able to return the bitmap argument immediately, while when called elsewhere or event elsewhere in the code of my view model I'll be able to await or cancel the task. Example 2: I want to be able to list files from a disk and get a task that is complete when all files have been listed, but immediately return an IObservableVector of view models representing the files for use in my XAML UI that updates as pages of the files are loaded asynchronously. Here I would probably do something similar: ``` public async Task<int> GetImages( object queryParemeters, out ObservableCollection<CustomFileInfoType> files, CancellationToken cancellationToken) ``` Problems Now the above look almost good, but I don't think I can expose a TPL Task outside a WinRT Component since `Task` is not a WinRT type, so I'd probably gave an internal method like the above and a public one that wraps the result as an `IAsyncOperation` by calling `AsyncInfo.Run()`, passing the task and cancellation token. `ObservableCollection` is also .NET only, so I'd probably need to create a wrapper around it that implements an `IObservableVector` since I don't think one is available in .NET. There are probably other potential problems with those and I am not sure if this design is right. Then also - how would I do all this in C++/CX? Or JS?