我正在尝试并行执行很多网络操作,并且我想为每个操作设置一个超时时间。
由于Parallel.ForEach没有简单的超时选项,因此我正在使用System.Reactive。
这是我的代码:
public void networkOps(List<MacCpe> source, Action<List<Router>, List<Exception>> onDone) {
var routers = new List<Router>();
var exceptions = new List<Exception>();
Observable.Defer(() => source.ToObservable())
.ObserveOn(Scheduler.CurrentThread)
.SubscribeOn(Scheduler.Default)
.SelectMany(it =>
Observable.Amb(
Observable.Start(() => {
switch(it.type) {
case AntennaType.type1: {
//network stuff
}
break;
case AntennaType.type2: {
//network stuff
}
break;
case AntennaType.type3: {
//network stuff
}
break;
case AntennaType.type4: {
//network stuff
}
break;
default: throw new NullReferenceException("Nothing");
}
}).Select(_ => true),
Observable.Timer(TimeSpan.FromSeconds(60)).Select(_ => false)
),
(it, result) => new { it, result }
)
.Subscribe (
x => {
Console.WriteLine("checked item number " + x.it.Id);
},
ex => {
Console.WriteLine("error string");
}, () => {
onDone(routers, exceptions);
}
);
}
我正在使用Observable.Amb运算符并行运行一个60秒的计时器,该计时器可以超时。
但是,当我运行此方法时,程序将立即退出,而无需进入onDone回调。
我在线看到可以在线程池上运行阻塞代码的同时使用ObserveOnDispatcher在Ui线程上进行观察,但是我正在终端应用程序服务器端的Linux上的dotnet核心上使用它。
在控制台应用程序中如何观察“主线程”?
预先感谢您的答复。
答案 0 :(得分:2)
在替换Parallel.ForEach
时,听起来好像很高兴进行屏蔽操作。使用Rx进行设置的方式不是阻塞操作,因此该方法立即结束。
修复非常简单。只需将您的.Subscribe
更改为此:
.Do(
x =>
{
Console.WriteLine("checked item number " + x.it.Id);
},
ex =>
{
Console.WriteLine("error string");
}, () =>
{
onDone(routers, exceptions);
}
)
.Wait();
在确定您需要.ObserveOn(Scheduler.CurrentThread)
和.SubscribeOn(Scheduler.Default)
之前,我也会摆脱它们。