反应式扩展、锁和线程
Posted
技术标签:
【中文标题】反应式扩展、锁和线程【英文标题】:Reactive Extensions, locks and threads 【发布时间】:2010-12-08 13:28:53 【问题描述】:我正在使用响应式扩展来处理 wpf ui,基本上我有一个文本框,我需要在小时间跨度(200-300毫秒)
问题在于它有些不可预测,有时会立即触发油门,这可能是因为 TextUpdated 事件没有到达可观察对象或可观察对象本身。我也在做一些可能会干扰的锁定,但这通常是通过新任务完成的,而不是在 UI 线程上。我还偷偷怀疑调试可能会影响行为,因为当我设置断点时它似乎更“不正确”地触发了
由于 observable 是在 UI 线程上创建的,我假设(可能是错误的)它是计时器或它在下面使用的任何东西也在该线程上,创建一个新线程来创建 observable 可能是个好主意,这样它就不会受到干扰通过 UI 开销和潜在的锁定?我如何以最好的方式设置这样一个线程,我猜它末尾的空while循环可能不是一个好主意:)
Throttle、Sample 工作以及与线程相关的响应式扩展如何在后台工作?
编辑
似乎问题出在我测试它的方式上:P 如果你按住一个键,它开始重复之前似乎有 500 毫秒的延迟,如果你只是敲击键它工作正常。叹息
【问题讨论】:
您是否大量使用 ThreadPool(除了通过 Sample/Throttle 隐式使用)? 【参考方案1】:Sample
和 Throttle
都使用 Scheduler.ThreadPool
作为他们的时间,所以我很怀疑这是问题所在。
我建议在代码中添加一些日志记录以找出瓶颈所在:
sourceEvents.LogInterval("Source")
.Throttle(throttleTimeSpan).LogInterval("Throttled")
.Sample(sampleTimeSpan).LogInterval("Sample")
.Subscribe();
这里是LogInterval
的定义:
public static class ObservableEx
public static IObservable<TSource> LogInterval(
this IObservable<TSource> source, string message)
return source
.TimeInterval()
.Do(x => Debug.WriteLine("0 :: 1 (2)",
message, x.Value, x.Interval.TotalMilliseconds);
.RemoveTimeInteval();
如果瓶颈是节流阀/样本,则可能意味着您在其他地方使线程池饱和。如果是这种情况,并且这些节流阀的性能很重要,您可以考虑创建一个专用线程+调度程序并为 Throttle/Sample 使用自定义 DistpatcherScheduler
。或者,可能有更好的 TPL 方法来解决它。
【讨论】:
问题是一个简化的版本,它只是一个 wpf 文本框和两个不同的响应式扩展连接到它的 textchanged observable 效果很好。当应用程序的负载增加时,问题似乎就开始了。可能是因为我也在使用并行扩展,我可能已经饱和了线程池或响应式扩展的东西? 查看更新以追踪瓶颈。是的,如果您大量使用 ThreadPool,则可能根本没有足够的可用资源。以上是关于反应式扩展、锁和线程的主要内容,如果未能解决你的问题,请参考以下文章