Reputation: 4286
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
Upvotes: 4
Views: 1835
Reputation: 84754
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.
Upvotes: 1