反应式扩展、锁和线程

发布于 2024-10-07 02:43:20 字数 565 浏览 0 评论 0原文

我正在使用反应式扩展来处理 wpf ui,基本上我有一个文本框,我需要在小时间跨度(200-300 毫秒)上进行采样和节流(在打字时连续做一些事情,在停止打字时做一些事情

)问题是它有些不可预测,有时会立即触发限制,这可能是因为 TextUpdated 事件没有到达可观察对象或可观察对象本身。我还做了一些可能会干扰的锁定,但这通常是通过新任务完成的,而不是在 UI 线程上完成的。我还偷偷怀疑调试可能会影响行为,因为当我设置断点时,它似乎会触发更多“错误”

由于可观察对象是在 UI 线程上创建的,我假设(可能是错误的)它的计时器或它在下面使用的任何内容也都在对于该线程,创建一个新线程来创建可观察值是否是一个好主意,这样它就不会受到 UI 开销和潜在锁定的干扰?我如何以最好的方式设置这样一个线程,我想在它末尾的空 while 循环可能不是一个好主意:)

Throttle、Sample 工作和与线程相关的反应式扩展如何在以下情况下工作无论如何?

编辑

似乎问题出在我测试它的方式上:P 如果你按住一个键,那么在开始重复之前似乎会有 500 毫秒的延迟,如果你只是敲击按键,它就可以正常工作。叹

I'm using reactive extensions to work with a wpf ui, basically I have a textbox I need to both do sampling and throttling (doing some stuff continously while typing and some stuff when stopped typing) on small timespans (200-300 ms)

The problem is that it's somewhat unpredictable and sometimes triggers throttle immediately, this might be because the TextUpdated event didnt make it to the observable or something with the observable itself. I'm also doing some locking that might interfer but that's typically done through new Tasks and not on the UI thread. I also have a sneaking suspicion that debugging might affect the behavior since it seems to trigger more "incorrectly" when I set breakpoints

Since the observable is created on the UI thread I assume (perhaps mistakenly) it's timer's or whatever it uses underneath is also on that thread, might it be a good idea to create a a new thread for creating the observables so it's not interfered by UI overhead and potential locking? How do I set up such a thread in the best way, I guess a empty while-loop at the end of it might not be such a good idea :)

How does Throttle, Sample work and reactive extensions in relationship with threads work under the hood anyway?

EDIT

Seems the problem was the way I was testing it :P If you hold down a key it seems there's a 500 ms delay before it starts repeating, if you just bang on the keys it works fine. Sigh

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云柯 2024-10-14 02:43:20

SampleThrottle 都使用 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();
    }
}

如果瓶颈是节流/样本,则可能意味着您在其他地方使 ThreadPool 饱和。如果是这种情况,并且这些限制的性能很重要,您可以考虑创建一个专用的线程+调度程序,并为 Throttle/Sample 使用自定义 DistpatcherScheduler。或者,可能有更好的 TPL 方法来解决它。

Both Sample and Throttle use Scheduler.ThreadPool for their timings so I high doubt that's the problem.

I recommend adding some logging to the code to find out where the bottleneck is:

sourceEvents.LogInterval("Source")
    .Throttle(throttleTimeSpan).LogInterval("Throttled")
    .Sample(sampleTimeSpan).LogInterval("Sample")
    .Subscribe();

Here is the definition of 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();
    }
}

If the bottleneck is the throttle/sample, it probably means you are saturating the ThreadPool elsewhere. If that is the case, and the performance of these throttles is important, you might consider creating a dedicated thread+dispatcher and using a custom DistpatcherScheduler for the Throttle/Sample. Alternatively, there might be a nicer TPL way of solving it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文