Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.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# 响应选通下一条消息发送,带有Rx_C#_Asynchronous_System.reactive_Blocking - Fatal编程技术网

C# 响应选通下一条消息发送,带有Rx

C# 响应选通下一条消息发送,带有Rx,c#,asynchronous,system.reactive,blocking,C#,Asynchronous,System.reactive,Blocking,给定一个列表我用我的send(message)发送第一条消息。现在我想等待(异步)响应返回,然后再发送下一条消息 阻塞,直到通知“旧”方式 我知道如何针对这种情况实施基于事件的解决方案,使用线程锁定/withMonitor.Wait和Monitor.Pulse 反应式“新”方式? 但我想知道在这里使用是否有意义 如果Rx在这里传递了有价值的好处,那么我如何才能在下一次发送调用中做出反应性的响应呢?很明显,它将涉及到可观测的,可能有两个作为主要来源,但接下来呢?我不确定Rx是否适合这里。Rx基于“

给定一个
列表
我用我的
send(message)
发送第一条消息。现在我想等待(异步)响应返回,然后再发送下一条消息

阻塞,直到通知“旧”方式 我知道如何针对这种情况实施基于事件的解决方案,使用线程锁定/with
Monitor.Wait
Monitor.Pulse

反应式“新”方式? 但我想知道在这里使用是否有意义


如果Rx在这里传递了有价值的好处,那么我如何才能在下一次发送调用中做出反应性的响应呢?很明显,它将涉及到可观测的,可能有两个作为主要来源,但接下来呢?

我不确定Rx是否适合这里。Rx基于“推送收集”的概念,即向消费者推送数据而不是拉取数据。您需要的是拉取第一项,异步发送它,并在异步操作完成后继续下一个元素。对于这种工作,最好的工具是异步/等待*

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

*在Async CTP或.NET 4.5预览版中提供

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

List<Message> messages;
IObservable<Response> xs;
xs =  messages.ToObservable().SelectMany(msg => Observable.FromAsyncPattern(Send, msg));
列出消息;
IObservable-xs;
xs=messages.ToObservable().SelectMany(msg=>Observable.fromsyncPattern(Send,msg));
编辑-这不会像Anderson建议的那样起作用,下面是一个显示问题的示例

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();
Func Send=(ii)=>{“in Send.Dump();Thread.Sleep(2000);return ii.ToString();};
Func sendIO=Observable.FromAsyncPattern(Send.BeginInvoke,Send.EndInvoke);
(新[]{1,2,3}).ToObservable().SelectMany(sendIO.Dump();

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

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

messages
    .ToObservable()
    .ObserveOn(Scheduler.ThreadPool)
    .Subscribe(m =>
    {
        Send(m);
    });
这会将对
Send
的调用推送到线程池,并且通过可观察对象的内置行为,每次对
Send
的调用都会等待,直到上一次调用完成

因为这一切都发生在不同的线程上,所以您的代码是非阻塞的

Rx的额外好处是,您无需更改
Send
方法的行为或签名即可实现此功能

简单,嗯


我测试了这个,考虑到我对你的问题的理解,它工作得很好。这就是你所需要的还是我遗漏了什么?

这个问题不是很具体,而且似乎很笼统,因为你没有提到什么是发送者-接收者等,所以答案也很笼统:)


能否显示更多现有的方法签名?Rx可能是一个很好的选择,但它的实现方式取决于您的起点推送收集和异步值序列之间的区别是什么?我真的很想选择您的响应作为答案,但鉴于Ankur使用合适的Rx解决方案进行了回答,它优先考虑。感谢堆让我知道异步CTP虽然!!是否会同时处理每条消息(取决于调度程序)?他似乎希望按顺序一次处理一个,一次处理一个是默认行为。这里有一个snipit
(新[]{1,2,3}).ToObservable().SelectMany(ii=>Observable.Return(ii).Do(dii=>{“in async Call.Dump();Thread.Sleep(5000);}))
一定是我缺少的东西。当我尝试这样做,但让第二个可观察对象本身花费很长时间(而不是在可观察对象上做一次)时,所有这些都会立即完成。请尝试
Observable.Return
,而不是
Observable.Start(()=>{Thread.Sleep(3000);Return ii;})
注意:我问这个问题是因为我遗漏了一些东西,而不是因为我认为你错了。这正是我想要的,我扩展了它以获得一些测试输出,下面是模拟的第一部分:
var startTime=DateTime.Now;var messages=(新[]{1,2,3}).ToObservable().Timestamp();var receiveObs=Observable.Generate(1,i=>i<4,i=>i+1,i=>answer+i.ToString(),i=>TimeSpan.FromSeconds(2)).Timestamp();receiveObs.Subscribe(resp=>Console.WriteLine(resp.Timestamp.Subtract(startTime).TotalSeconds+”秒,这是业务结束:
var iterations=messages.Select(m=>{Console.WriteLine(m.Timestamp.Subtract(startTime).TotalSeconds+”秒->发送消息“+m.Value);receiveObs.First();return m.Value;}).Timestamp();iterations.Subscribe(time=>Console.WriteLine(time.Timestamp.Subtract(startTime).TotalSeconds+“秒处理”+time.Value+“完成”));
最后是控制台输出:
0.109sec->Sent message 1 2.112sec Sent message 2 4.12sec Sent message 3 6.132sec这不起作用,请参阅Enigmativity注释:“您意识到,每次调用receiveObs.First()你从一开始就开始观察?你的接收观察是“冷的”。你不分享观察-你创造了四个实例。"是的,如果receiveObs是冷可观察的,那么它将不起作用,但是您没有提到您的可观察对象是冷的。很抱歉,对于要求不透明,Send方法与Receive回调是分开的,因此Send将在响应返回之前完成;即,此代码似乎没有达到选通desired@Cel-你能告诉我是什么吗至少,这不是你所需要的吗?简言之,这篇文章的公认答案中没有提到receiveObs。我相信Ankur答案评论中的代码与你的建议不同。@Cel-如果我是你,我会再看看Ankur的答案和评论中的代码。
Receive
messages
    .ToObservable()
    .ObserveOn(Scheduler.ThreadPool)
    .Subscribe(m =>
    {
        Send(m);
    });
var receiveObs = //You have created a observable around the receive mechanism 
var responses = messages.Select(m => {
   send(m);
   return receiveObs.First();
}).ToList();