.net - 为远程调用实现 Task<T> 而不是在事件中响应?

标签 .net task-parallel-library

我有一个 API,其界面如下所示:

void SendRequest(Guid id, IRequest request);
event EventHandler<ResponseEventArgs> ResponseReceived;

实现此方法的最佳方式是什么?

Task<T> GetResponse(IRequest request) where T: IRequest

请注意,多个请求可能会相互重叠,因此当响应返回时,我需要查找父请求。我有一种感觉 TaskCompletionSource 可能有用,但不能完全拼凑起来。

最佳答案

编辑:

如果您想在不阻塞线程的情况下执行此操作,您可以使用 TaskCompletionSource<T> 执行类似的操作:

var completionSource = new TaskCompletionSource<T>();

var requestIdentifier = Guid.NewGuid();

EventHandler<ResponseEventArgs> handler = null;

handler = (sender, args) =>
{
    if(args.RequestIdentifier == requestIdentifier)
    {
        api.ResponseReceived -= handler; 

        // TrySetResult avoids re-entrancy problems in case of an
        // API that sends duplicates, but there other ways of 
        // dealing with this too.
        completionSource.TrySetResult((T)args.Response);
    }      
};


api.ResponseReceived += handler; 

// Make this async if you want.
api.SendRequest(requestIdentifier, request); 

return completionSource.Task;

原始答案:

我想你想要类似下面的东西,它使用 ManualResetEvent 阻塞线程,直到 API 引发事件:

return Task.Factory.StartNew<T>(() =>
{
    var waitHandle = new ManualResetEvent(false);

    T result = default(T);

    var requestIdentifier = Guid.NewGuid();

    EventHandler<ResponseEventArgs> handler = (sender, args) =>
    {
         if(args.RequestIdentifier == requestIdentifier)
         {
             result = (T)args.Response; // Not sure how this looks in your API
             waitHandle.Set(); // Unblock the thread running the task     
         }      
    };

    // Attach handler to respond to the response being received.
    api.ResponseReceived += handler; 

    // Send request off.
    api.SendRequest(requestIdentifier, request); 

    // Wait until response is received.
    waitHandle.WaitOne(); 

    // Detach handler to prevent leak.
    api.ResponseReceived -= handler; 

    return result;
});

要获得更简洁的方法,请查看 Reactive Extensions .

关于.net - 为远程调用实现 Task<T> 而不是在事件中响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11438832/

相关文章:

c# - 获取 HTML 表格数据

task-parallel-library - 具有分离队列的多生产者多消费者数据同步

c# - await 关键字可以生成并行代码吗?

c# - 带有字符串参数的 MongoDb c# Driver typed Builder

.net - 从 vb.net 中的 List(Of t) 中删除项目失败

c# - 为什么我需要成为管理员才能读取 .NET CLR 内存性能计数器

c# - 为什么任务在执行下一个代码之前等待Task.Run而不是Task.Factory.StartNew?

c# - 从任务并行库更新 ProgressBar UI 对象

c# - 不等待 HttpClient 使用时会发生什么

c# - 我可以在 Moq 中重用 It.Any 参数描述符吗