[英]How to wait for a value or until a fixed amount of time has elapsed using Reactive Extensions (Rx.Net)
I want to wait (block) a thread until either a time has elapsed or another stream pumps a value, I thought the following might achieve this but it throws an exception because the first stream is empty, 我想等待(阻塞)一个线程,直到时间已经过去或另一个流泵出一个值,我认为以下可能会实现这一点,但它会引发异常,因为第一个流是空的,
// 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();
How can I achieve the ability to block for up to 5 seconds or until the other stream pumps a value? 如何实现阻止最多5秒或直到另一个流泵出值的能力?
You can use Observable.Timeout
like this: 您可以像这样使用Observable.Timeout
:
var result = _updates.Take(1).Timeout(DateTime.Now.AddSeconds(5)).Wait();
I use Take(1)
because timeout expects sequence to complete, not just produce next value. 我使用Take(1)
因为timeout需要序列完成,而不仅仅是产生下一个值。 On timeout it will throw System.TimeoutException
. 在超时时,它将抛出System.TimeoutException
。
If you don't want exception - you can use Catch
to provide some value instead: 如果您不想要例外 - 您可以使用Catch
来提供一些值:
var result = _updates.Take(1).Timeout(DateTime.Now.AddSeconds(5))
.Catch(Observable.Return(default(Unit))).Wait();
// should catch specific exception, not all
If your Unit
is indeed that rx unit mentioned by @Shlomo - you can change it like this: 如果您的Unit
确实是@Shlomo提到的rx单位 - 您可以像这样更改它:
var result = _updates.Select(c => (Unit?) c).Take(1)
.Timeout(DateTime.Now.AddSeconds(5)).Catch(Observable.Return((Unit?) null)).Wait();
or just catch that exception as usual. 或者像往常一样抓住那个例外。
Here's another alternative if you don't want to deal with exceptions: 如果您不想处理异常,这是另一种选择:
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;
}
Can you create two tasks and then do a wait any? 你能创建两个任务然后再等待吗? That would likely be the "easiest" way to achieve that. 这可能是实现这一目标的“最简单”方式。
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>
Edit: Title changed to specify React, answer probably wouldn't be applicable anymore. 编辑:标题已更改为指定React,答案可能不再适用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.