我对如何最好地处理这种情况感到困惑。我不想等待异步调用的响应。具体来说,我有:
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 实现的,超出了我的控制范围。
当消息就绪或发生超时时,队列会公开一个事件。这是您通常检查是否存在消息的地方,然后根据文档调用 EndReceive。标准听众....
ReadQueue.ReceiveCompleted += ReadQueue_ReceiveCompleted;
我的问题是我不明白如何做到这一点并且仍然可以等待(即我希望能够像现在一样等待,但要通过委托(delegate)来处理)。这有意义吗?
最佳答案
通常,当您想将一些非基于任务的异步模型转换为基于任务的异步模型时,如果还没有 Task
方法为您进行转换,您可以使用TaskCompletionSource
以“手动”处理每种情况:
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;
}
您需要根据未显示的类型的具体情况进行调整,但这是一般的想法。
关于c# - 等待与事件处理程序异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20252696/