C# 如何使用反应式扩展(Rx.Net)等待一个值或直到经过一段固定的时间
我想等待(阻塞)一个线程,直到一段时间过去或者另一个流输出一个值,我认为下面的方法可能会实现这一点,但它会抛出一个异常,因为第一个流是空的C# 如何使用反应式扩展(Rx.Net)等待一个值或直到经过一段固定的时间,c#,system.reactive,C#,System.reactive,我想等待(阻塞)一个线程,直到一段时间过去或者另一个流输出一个值,我认为下面的方法可能会实现这一点,但它会抛出一个异常,因为第一个流是空的 // class level subject manipulated by another thread... _updates = new Subject<Unit>(); ... // wait for up to 5 seconds before carrying on... var result = Observable
// class level subject manipulated by another thread...
_updates = new Subject<Unit>();
...
// wait for up to 5 seconds before carrying on...
var result = Observable.Timer(DateTime.Now.AddSeconds(5))
.TakeUntil(_updates)
.Wait();
//类级主题被另一个线程操纵。。。
_更新=新主题();
...
//最多等待5秒钟,然后继续。。。
var result=Observable.Timer(DateTime.Now.AddSeconds(5))
.TakeUntil(_更新)
.Wait();
我如何才能实现最多5秒的阻塞,或者直到其他流泵出一个值为止?您可以使用
可观察超时
如下所示:
var result = _updates.Take(1).Timeout(DateTime.Now.AddSeconds(5)).Wait();
var result = _updates.Select(c => (Unit?) c).Take(1)
.Timeout(DateTime.Now.AddSeconds(5)).Catch(Observable.Return((Unit?) null)).Wait();
我使用Take(1)
,因为超时要求序列完成,而不仅仅是生成下一个值。超时时,它将抛出System.TimeoutException
如果您不希望出现异常-您可以使用Catch
来提供一些值:
var result = _updates.Take(1).Timeout(DateTime.Now.AddSeconds(5))
.Catch(Observable.Return(default(Unit))).Wait();
// should catch specific exception, not all
如果您的装置
确实是@Shlomo提到的接收装置-您可以这样更改:
var result = _updates.Take(1).Timeout(DateTime.Now.AddSeconds(5)).Wait();
var result = _updates.Select(c => (Unit?) c).Take(1)
.Timeout(DateTime.Now.AddSeconds(5)).Catch(Observable.Return((Unit?) null)).Wait();
或者像往常一样捕获异常。您可以创建两个任务,然后执行等待吗?这可能是实现这一目标的“最简单”的方法
var waitTask = new Task(() => Thread.Sleep(5000));
var messageTask = new Task(() => <listen for input and return>);
await Task.WhenAny(waitTask, messageTask);
<the rest of your code>
var waitTask=新任务(()=>Thread.Sleep(5000));
var messageTask=新任务(()=>);
wait Task.whenay(waitTask,messageTask);
编辑:标题更改为指定React,答案可能不再适用。如果您不想处理异常,这里有另一种选择:
var _updates = new Subject<Unit>();
var result = Observable.Merge(
_updates.Materialize(),
Observable.Empty<Unit>()
.Delay(TimeSpan.FromSeconds(5))
.Materialize()
)
.Take(1)
.Wait();
switch (result.Kind)
{
case NotificationKind.OnCompleted:
//time's up, or someone called _updates.OnCompleted().
break;
case NotificationKind.OnNext:
var message = result.Value;
//Message received. Handle message
break;
case NotificationKind.OnError:
var exception = result.Exception;
//Exception thrown. Handle exception
break;
}
var\u updates=新主题();
var结果=可观察。合并(
_updates.Materialize(),
可观察的。空的()
.延迟(时间跨度从秒(5))
.具体化
)
.采取(1)
.Wait();
开关(result.Kind)
{
案例通知种类.未完成:
//时间到了,或者有人打电话给_updates.OnCompleted()。
打破
案例通知种类.OnNext:
var message=result.Value;
//收到消息。处理消息
打破
案例通知Kind.OnError:
var exception=result.exception;
//引发异常。处理异常
打破
}
我不知道这是否重要,但是默认值(单位)=单位。默认值==新单位()
,因此结果将始终具有相同的值。@Shlomo不确定您的意思。如果更新序列产生一个值-结果将是该值,而不是默认值。如果单位是类,则默认(单位)为空。也许OP是指一些我不知道的特定单元,但我把单元当作任意类来对待。他可能指的是System.Reactive.Unit,它是一个结构,而不是一个类。看见