获取第一个IObservable事件,而不阻塞想要它的线程/任务

时间:2017-07-14 15:39:23

标签: c# multithreading reactive

我正在考虑使用IObservable在ac#async方法中的请求 - 响应环境中获取响应并替换一些旧的基于回调的代码,但我发现如果推送了一个值(Subject.OnNext)对于可观察但FirstAsync还没有等待,那么FirstAsync永远不会得到该消息。

有没有直接的方法让它工作,没有第二个任务/线程加同步?

public async Task<ResponseMessage> Send(RequestMessage message)
{
    var id = Guid.NewGuid();
    var ret = Inbound.FirstAsync((x) => x.id == id).Timeout(timeout); // Never even gets invoked if response is too fast
    await DoSendMessage(id, message);
    return await ret; // Will sometimes miss the event/message
}

// somewhere else reading the socket in a loop
// may or may not be the thread calling Send
Inbound = subject.AsObservable();
while (cond)
{
    ...
    subject.OnNext(message);
}

在我发送请求之前,我无法将await放到FirstAsync,因为这会阻止请求被发送。

2 个答案:

答案 0 :(得分:1)

await将订阅观察者。您可以通过调用await

将订阅与ToTask分开
public async Task<ResponseMessage> Send(RequestMessage message)
{
  var id = Guid.NewGuid();
  var ret = Inbound.FirstAsync((x) => x.id == id).Timeout(timeout).ToTask();
  await DoSendMessage(id, message);
  return await ret;
}

答案 1 :(得分:1)

我仔细研究了一下,通过将热转换为冷可观察性,可以很容易地解决您的问题。将Subject替换为ReplaySubject。以下是文章:http://www.introtorx.com/content/v1.0.10621.0/14_HotAndColdObservables.html

  

以下是解释:

     

Replay扩展方法允许您获取现有的observable   序列并根据ReplaySubject给它'重放'语义。作为一个   提醒一下,ReplaySubject将缓存所有值,以便任何迟到   订阅者也将获得所有价值。