Following the example in this article my rudimentary approach (untested!!) would be:
class AsyncCamera
{
private readonly Camera camera;
public AsyncCamera(Camera camera)
{
this.camera = camera ?? throw new ArgumentNullException(nameof(camera));
}
public Task<ReadResult> CaptureAsync()
{
TaskCompletionSource<ReadResult> tcs = new TaskCompletionSource<ReadResult>();
camera.OnReadResult += (sender, result) => {
tcs.TrySetResult(result);
};
camera.RequestCapture();
return tcs.Task;
}
}
Possible usage:
public async Task DoSomethingAsync()
{
var asyncCam = new AsyncCamera(new Camera());
var readResult = await asyncCam.CaptureAsync();
// use readResult
}
EDIT taking Stephen's comment into account (T H A N K you!)
So, this is my naive take on unsubscribing the event handler. I didn't have the time to make any tests, so suggestions for improvement are welcome.
class AsyncCamera
{
private readonly Camera camera;
public AsyncCamera(Camera camera)
{
this.camera = camera ?? throw new ArgumentNullException(nameof(camera));
}
public Task<ReadResult> CaptureAsync()
{
ReadResultEventHandler handler = null;
TaskCompletionSource<ReadResult> tcs = new TaskCompletionSource<ReadResult>();
handler = (sender, result) => {
camera.OnReadResult -= handler;
tcs.TrySetResult(result);
};
camera.OnReadResult += handler;
camera.RequestCapture();
return tcs.Task;
}
}
In case comments get "cleaned up": Stephen said
Unsubscription isn't handled in the MS examples, but it really should be. You'd have to declare a variable of type ReadResultDelegate (or whatever it's called), set it to null, and then set it to the lambda expression which can then unsubscribe that variable from the event. I don't have an example of this on my blog, but there's a general-purpose one here. Which, now that I look at it, does not seem to handle cancellation appropriately. – Stephen Cleary
Emphasis by me.
Seems to work: https://dotnetfiddle.net/9XsaUB