Multiple tasks <T> or IProgress <T> for partial completion?
I use an asynchronous operation that completes in three steps, returning partial results to completion. It initially uses events to track progress, and I want to correctly wrap it as an await
operation (or a chain of them).
More precisely, this is the PhotoCamera.CaptureImage method in Windows Phone 7, which fires events in the following order (with the corresponding result types):
CaptureStarted
, not that interesting to meCaptureThumbnailAvailable
(stream)CaptureImageAvailable
(stream)CaptureCompleted
(bool)
How to wrap it? I am currently using TaskCompletionSource
and SetResult
on CaptureCompleted
. It does not affect steps 2 and 3, thumbnail and image become available. I decided to use callbacks for them.
My extension method (for brevity, let's leave the code):
public static Task<bool> CaptureImageAsync(this PhotoCamera photoCamera, Action<Stream> thumbnailAvailableCallback, Action<Stream> imageAvailableCallback)
It does not seem completely clean, it is a mixture of tasks and callbacks. I know IProgress<T>
. However, the progress values ββdo not have the same type (Stream, Stream, bool) ... and is the IProgress<T>
template too stretched?
Using multiple Task<T>
, expected in order, is an option, but it involves a certain order, which I will also need to somehow provide. Perhaps each result of the task may contain the following task as a member:
ThumbnailResult thumbnailResult = await photoCamera.CaptureImageAsync(); ... ImageResult imageResult = await thumbnailResult.NextTask; ... bool finalResult = await imageResult.NextTask;
I still think I'm a little from here. Ideas?
Personally, I will create a class for it with 3 methods that return Task<T>
. The caller will be able to call 3 methods in any order, and it will always work. if GetFinalResultAsync
is called first, and then GetThumbnailAsync
, then only the consequence is that the second Task<T>
will have a result when await is used, and it will return synchronously.
var photoCapture = photoCamera.BeginCapture(); var thumbnailResult = await photoCapture.GetThumbnailAsync(); var imageResult = await photoCapture.GetImageAsync(); var finalResult = await photoCapture.GetFinalResultAsync();
Waiting for everything:
var thumbnailTask = photoCapture.GetThumbnailAsync(); var imageTask = photoCapture.GetImageAsync(); var finalTask = photoCapture.GetFinalResultAsync(); await Task.WhenAll(thumbnailTask, imageTask, finalTask); DoWork(thumbnailTask.Result, imageTask.Result, finalTask.Result);