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,它是一个结构,而不是一个类。看见