Await async with event handler
asynchronous, c#, msmq
Solution
As a rule when you want to convert some non-task based asynchronous model to a task based asynchronous model, if there isn't already a `Task` method to do the conversion for you, you use a `TaskCompletionSource` to handle each of the cases "manually":
public Task<IApiData> FetchQueuedApiAsync(TimeSpan receiveTimeout)
{
var tcs = new TaskCompletionSource<IApiData>();
ReadQueue.BeginReceive(receiveTimeout);
ReadQueue.ReceiveCompleted += (sender, args) =>
{
if (timedOut)
tcs.TrySetCanceled();
else if (threwException)
tcs.TrySetException(exception);
else
tcs.TrySetResult(ReadQueue.EndReceive() as IApiData);
};
return tcs.Task;
}
You'll need to adjust this based on the specifics of the types you didn't show, but this is the general idea.
Problem
I am confused as to how best handle this situation. I wan't to await the response of an asynchronous call. Specifically I have: ``` public async Task<IApiData> FetchQueuedApiAsync(TimeSpan receiveTimeout) { var message = await Task.Factory.FromAsync<Message>( ReadQueue.BeginReceive(receiveTimeout), ReadQueue.EndReceive); return message.Body as IApiData; } ``` This works as expected. However, if the timeout expires then ReadQueue.EndReceive must not be called else it will throw an exception. Obviously FromAsync doesn't know this and calls it blindly - firing the exception. The requirement not to call EndReceive on timeouts is implemented by MSMQ and beyond my control. The queue exposes an event when a message is ready or a timeout occurs. This is where you would normally check if a message was present, and THEN call EndReceive as per the documentation. Standard listener.... ``` ReadQueue.ReceiveCompleted += ReadQueue_ReceiveCompleted; ``` My question is that I don't understand how to do that and still have this as awaitable (i.e. I want to be able to await like I have now, but handle it via the delegate). Does that make sense?