等待与异步事件处理程序 [英] Await async with event handler

查看:144
本文介绍了等待与异步事件处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很困惑,如何最好地处理这种情况。我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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆