等待与异步事件处理程序 [英] Await async with event handler
问题描述
我很困惑,如何最好地处理这种情况。我wan't以等待异步调用的响应。具体来说,我有:
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;
}
这正常工作。但是,如果超时则ReadQueue.EndReceive不得别人叫会抛出异常。显然FromAsync不知道这一点,盲目地称之为 - 射击例外。不叫EndReceive对超时的需求由MSMQ和超出了我的控制来实现。
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.
当消息准备或发生超时队列公开的事件。这是,你通常会检查,如果消息是present,然后调用EndReceive按文档。标准听众....
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;
我的问题是,我不知道如何做到这一点,仍然有这个作为awaitable(即我希望能够像等待我现在有,而是通过委托处理它)。这是否有意义?
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?
推荐答案
当你想一些非基于任务的异步模型转换为基于异步模型,任务如果没有已经是<$ C $规则C>工作方法做转换为你,你用 TaskCompletionSource
来处理每个案件手动:
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.
这篇关于等待与异步事件处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!