c# - 等待与事件处理程序异步

标签 c# asynchronous msmq

我对如何最好地处理这种情况感到困惑。我不想等待异步调用的响应。具体来说,我有:

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/

相关文章:

.net - MSMQ:传送到远程队列时未返回确认

msmq - 无法读取远程专用队列

c# - 从中间有非数字的字符串中解析数字

c# HMACSHA256 加密到 php 中的 HMACSHA256

c# - 将图像从浏览器拖放到 WPF 应用程序

javascript - 在测试执行之前从模块加载数据

node.js - node.js 是否保留异步执行顺序?

c# - 通过已知端口进行服务器间通信

c# - WPF如何根据窗口大小调整某个控件的大小?

c# - 异步异常未被捕获或被吞噬