我想使用IObservable.Timeout()
来检测数据源是否已“脱机”。此数据源是在循环内读取的串行连接。
读操作是故意阻塞的,如果我在预定义的时间内没有收到任何数据,我想取消操作。否则,每次我收到数据时,我都希望超时可观察量生成一个项目,从而重置超时。
我的怀疑是以下评论的形式:
void Run()
{
IObservable<object> timeoutWatcher = CreateResettableTimer();
timeoutWatcher.Timeout(TimeSpan.FromSeconds(1)).Subscribe(_cancellation.Cancel());
while (!_cancellation.IsCancellationRequested)
{
var frameVals = FTDIHelper.ReadAvailableBytes(_handle, 8); // blocking;
DoSomethingWith(frameVals);
// ??? How do I "add" an item to timeoutWatcher ???
}
}
IObservable<object> CreateResettableTimer()
{
// ??? What should I return, and how to create it ???
// Use a Subject? If not, what else then?
// Should it be returning IObservable<object> or other type?
}
答案 0 :(得分:2)
您可以使用Timeout
运算符为可在指定时间内未生成值的observable指定超时(这具有语义意义)。超时传播您可以订阅的OnError
- 这确实会导致超时管道被拆除,但您可以使用Retry
来应用重新订阅逻辑。使用OnError
应用取消逻辑。您还可以通过同一个管道处理非超时错误。
这是一个模拟任务的示例&#39;需要花费一段时间才能完成,如果超过两秒钟就会检测到超时。
var randomSource =
Observable.Defer(() => Observable.Timer(TimeSpan.FromSeconds(new Random().NextDouble() * 5))).Repeat().Publish();
randomSource
.Do(v => Console.WriteLine(DateTime.Now))
.Timeout(TimeSpan.FromSeconds(2))
.Do(_ => { }, err => Console.Write("\t\t\tTimed out\r")) //on error callback
.Retry()
.Subscribe(); //set up the pipeline
randomSource.Connect();
Console.ReadLine();
输出:
6/26/2017 7:15:42 PM Timed out
6/26/2017 7:15:43 PM
6/26/2017 7:15:46 PM Timed out
6/26/2017 7:15:47 PM
6/26/2017 7:15:51 PM Timed out
6/26/2017 7:15:56 PM Timed out
6/26/2017 7:16:00 PM Timed out
6/26/2017 7:16:02 PM
6/26/2017 7:16:02 PM
6/26/2017 7:16:05 PM Timed out
6/26/2017 7:16:06 PM
6/26/2017 7:16:08 PM
6/26/2017 7:16:08 PM
6/26/2017 7:16:10 PM
6/26/2017 7:16:13 PM Timed out
6/26/2017 7:16:18 PM Timed out
如您所见,任何超过两秒的时间都会超时。