使用Rx响应门控下一条消息发送

时间:2011-09-21 21:14:39

标签: c# asynchronous system.reactive blocking

给定List<Message>我发送带有Send(message)的第一封邮件。现在我想等待(异步)响应在我发出下一条消息之前回来......

阻止直到通知'旧'方式

我知道如何使用线程锁定/ Monitor.WaitMonitor.Pulse

为这种情况实现基于事件的解决方案

反应'新'的方式?

但我想知道在这里使用Reactive Extensions是否有意义

如果Rx在这里传达了有价值的好处,那么如何可以使响应被动地响应下一次发送调用?显然它会涉及IObservable,可能有两个作为主要来源,但接下来是什么?

4 个答案:

答案 0 :(得分:2)

我认为Rx在这里是个不错的选择,但我想我可能会在你的要求中遗漏一些东西。根据我的理解,Rx提供了一个非常简单的解决方案。

如果您已经有一个消息列表,那么您可以像这样反复发送它们:

messages
    .ToObservable()
    .ObserveOn(Scheduler.ThreadPool)
    .Subscribe(m =>
    {
        Send(m);
    });

这会将对Send的调用推送到线程池,并且通过observable的内置行为,每次调用Send都会等到上一次调用完成。

由于这一切都发生在不同的线程上,因此您的代码是非阻塞的。

Rx的额外好处是您无需更改Send方法的行为或签名即可使其正常工作。

简单,是吗?

我对此进行了测试,并且考虑到我对您的问题的理解,它运行良好。这是你需要的还是我错过的东西?

答案 1 :(得分:2)

这个问题不是很具体,而且在你没有提到什么是发送者接收者等的意义上似乎很一般,所以答案也很一般:)

var receiveObs = //You have created a observable around the receive mechanism 
var responses = messages.Select(m => {
   send(m);
   return receiveObs.First();
}).ToList();

答案 2 :(得分:1)

我不确定Rx是否适合这里。 Rx基于“推送集合”的概念,即将数据推送给消费者而不是拉动消费者。你想要的是拉出第一个项目,异步发送它,并在异步操作完成时继续下一个元素。对于这种工作,完美的工具将是异步 / 等待*

async void SendMessages(List<Message> messages)
{
    foreach (Message message in messages)
    {
        await SendAsync(message);
    }
}

Task SendAsync(Message message);

* 在Async CTP或.NET 4.5预览版

中可用

答案 3 :(得分:1)

假设您的Send方法遵循APM模型,以下方法应该适合您

List<Message> messages;
IObservable<Response> xs;
xs =  messages.ToObservable().SelectMany(msg => Observable.FromAsyncPattern(Send, msg));

编辑 - 这不会像安德森所说的那样有效,这是一个显示问题的例子

Func<int,string> Send = (ii) => { "in Send".Dump(); Thread.Sleep(2000); return ii.ToString(); };
Func<int,IObservable<string>> sendIO =  Observable.FromAsyncPattern<int,string>(Send.BeginInvoke, Send.EndInvoke);
(new [] { 1, 2, 3 }).ToObservable().SelectMany(sendIO).Dump();