Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用事件处理程序等待异步_C#_Asynchronous_Msmq - Fatal编程技术网

C# 使用事件处理程序等待异步

C# 使用事件处理程序等待异步,c#,asynchronous,msmq,C#,Asynchronous,Msmq,我对如何最好地处理这种情况感到困惑。我不想等待异步调用的响应。具体而言,我有: public async Task<IApiData> FetchQueuedApiAsync(TimeSpan receiveTimeout) { var message = await Task.Factory.FromAsync<Message>( ReadQueue.BeginReceive(receiveTimeout), ReadQueue.EndRecei

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

public async Task<IApiData> FetchQueuedApiAsync(TimeSpan receiveTimeout)
{
    var message = await Task.Factory.FromAsync<Message>(
        ReadQueue.BeginReceive(receiveTimeout), ReadQueue.EndReceive);
    return message.Body as IApiData;
 }

我的问题是,我不知道如何做到这一点,但仍然可以等待(即,我希望能够像现在一样等待,但通过代表处理)。这有意义吗?

通常,当您想要将一些非基于任务的异步模型转换为基于任务的异步模型时,如果还没有一个
任务
方法来为您进行转换,您可以使用
任务完成源
来“手动”处理每种情况:

公共任务FetchQueuedApiAsync(TimeSpan receiveTimeout) { var tcs=new TaskCompletionSource(); ReadQueue.BeginReceive(接收超时); ReadQueue.ReceiveCompleted+=(发送方,参数)=> { if(timedOut) tcs.trysetconceled(); 否则如果(例外情况) tcs.TrySetException(例外); 其他的 tcs.TrySetResult(ReadQueue.EndReceive()作为IApiData); }; 返回tcs.Task; }

您需要根据未显示的类型的具体情况对此进行调整,但这是总体思路。

我认为这正是我想要的。我不确定事件侦听器在这里是如何工作的。是否每次调用函数时都要向ReceiveCompleted添加一个新的处理程序?考虑到这是所谓的地段,我需要清理一下吗?ReadQueue也在几个并发线程之间共享。如果多个线程正在侦听ReceiveCompleted,那么它们是否都收到了向它们引发的事件?@AndySavage如果不进一步了解您正在处理的特定类,我真的不能这么说。理想情况下,只有一个方法将在异步事件完成时被调用。如果事件是共享的,那么您需要确定完成的事件是否对应于“this”请求。您还需要在完成任务时删除处理程序,是的。或者,另一种方法是将一个处理程序永久附加到接收队列,该队列的任务是确定哪个任务负责并正确设置它。
ReadQueue.ReceiveCompleted += ReadQueue_ReceiveCompleted;
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;
}