c# - Smooth chart update from multithreaded data source -
we have several graphs show filtered data surface emg sensors. data received on tcp , propagated using event. datapackets of type datapackets , such filtered out. i'm using buffer let packets pass through @ 30fps. i'm listening event using reactive extensions follows:
observable.fromevent<packet>(h => this.dataservice.packetreceived += h, h=> this.dataservice.packetreceived -= h) .oftype<datapacket>() .buffer(timespan.fromseconds(1.0 / 30)) .observeondispatcher() .subscribe( packet => this.receivedatapackets(packet.tolist()), err => this.log.error("error subscribing data packets", err), () => this.log.info("finished listening data packets"));
to display emg data use telerik chartview. problem i'm having data update not smooth, graph choppy.
there several reasons this:
- telerik chart not fast enough 1000 data points per second
- dispatchertimer not fire @ constant rate
- data not received @ constant rate
point 1 solved sampling input data 1000 points visible in graph.
point 2 cannot solved unfortunately. tried raising priority render not @ all. http://social.msdn.microsoft.com/forums/en-us/5eea6700-1c79-4da6-9b68-efa480ed3a36/simplify-wpf-dispatcher-calls?forum=rx
point 3 related point 2. try solve both timed queue using system.debug.stopwatch
. datapackets contain timestamp , used let them through @ constant rate on dispatcher thread. suspect not since dispatcherrate not linked refresh rate of renderthread.
what can reduce choppiness? tried lightningchart ultimate supposed much faster. indeed have better performance , there no need sampling, can render each , every datapoint. samples provided lightningchart run butter smooth, read data in main thread. when implement chart in our multi-threaded program still suffers combination of point 2 , 3 (and fact more expensive telerik chartview.)
[update]
classic mistake. datasource using dispatchertimer gather data. changing observable.interval massively increased performance.
i have had similar troubles chart control a while ago. found charting controls not handle 1000+ datapoints. found trying re-render more 5-15 times per second pretty tough on dispatcher.
things suggest are:
- aim lower frame rate. hoping updates chart every 33ms?
- look reduce data set 1000 points. again play numbers see works target spec pc , controls/datatemplating. this old post may you. provides way pick x useful points render collection
- dial fancy animations or ui rendered per point on chart. if adding more items each have tool tips, brushes, animations , excess layout panels, pay cost. note not pay cost created, later when gc tries clear out these thousands of ui objects.
- do less work on dispatcher. know not much, move
tolist()
, on other thread. also, dont send empty lists processed (if applicable events) consider using d3/ddd charts. while not great when reviewed them, colleagues have had success them since then.
observable.fromevent<packet>(h => this.dataservice.packetreceived += h, h=> this.dataservice.packetreceived -= h) .oftype<datapacket>() .buffer(timespan.fromseconds(1.0 / 8)) //reduce fps .select(packet=>packet.tolist()) //reduce work done on dispatcher .where(packet=>packet.count>0) //dont send empty sets dispatcher .observeondispatcher() .subscribe( packet => this.receivedatapackets(packet), err => this.log.error("error subscribing data packets", err), () => this.log.info("finished listening data packets"));
i not sure if helps, here another link code presentation. part of presentation how stream data via rx wpf chart. potentially rip whole thing.
Comments
Post a Comment