给定List<Message>
我发送带有Send(message)
的第一封邮件。现在我想等待(异步)响应在我发出下一条消息之前回来......
我知道如何使用线程锁定/ Monitor.Wait
和Monitor.Pulse
但我想知道在这里使用Reactive Extensions是否有意义?
如果Rx在这里传达了有价值的好处,那么如何可以使响应被动地响应下一次发送调用?显然它会涉及IObservable
,可能有两个作为主要来源,但接下来是什么?
答案 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();