c# - Batch updating UI component through observable collection with large amounts of data WinRT -
i have winrt application fires notifications everytime recieves data device. have ui control databound observable collection wish add new data to
while have made capable of updating observable collection, causes ui become laggy, amount of data generated fast. therefore better batch update, maybe every few hundred milliseconds.
below shows snippet of code. first create periodic timer
timerelapsedhandler f = new timerelapsedhandler(batchupdate); createperiodictimer(f, new timespan(0, 0, 3));
below event handler when new data comes in, along temporary list stores information
list<financialstuff> lst = new list<financialstuff>(); async void mydata_valuechanged(gattcharacteristic sender, gattvaluechangedeventargs args) { var data = new byte[args.characteristicvalue.length]; datareader.frombuffer(args.characteristicvalue).readbytes(data); lst.add(new financialstuff() { time = "datetime.utcnow.tostring("mm:ss.ffffff")", amount = data[0] }); }
then batch update, called peroidically
private void batchupdate(threadpooltimer source) { additem<financialstuff>(financialstufflist, lst); }
then finally, testing want clear observable collection , items.
public async void additem<t>(observablecollection<t> oc, list<t> items) { lock (items) { if (dispatcher.hasthreadaccess) { foreach (t item in items) oc.add(item); } else { dispatcher.runasync(coredispatcherpriority.low, () => { oc.clear(); (int = 0; < items.count; i++) { items.count()); oc.add(items[i]); } lst.clear(); }); } } }
while seems work, after few updates ui locks , updates slowly/if not @ all. testing, it's getting few hundred items in list time timer fired.
can enlighten me why why happening - i'm presuming design poor.
thanks
you're not locking list in event handler
// "lst" never locked in event handler list<financialstuff> lst = new list<financialstuff>(); lst.add(new financialstuff() { time = "datetime.utcnow.tostring("mm:ss.ffffff")", amount = data[0] });
passing "lst" above async method
additem<financialstuff>(financialstufflist, lst);
you're locking "items" below, "lst" above. however, you're adding list while processing it. assume event handler has higher priority processing slower add. can lead "i < items.count" being true forever.
public async void additem<t>(observablecollection<t> oc, list<t> items) { // "lst" reference locked here, wasn't locked in event handler lock (items) { if (dispatcher.hasthreadaccess) { foreach (t item in items) oc.add(item); } else { dispatcher.runasync(coredispatcherpriority.low, () => { oc.clear(); // may never exit loop (int = 0; < items.count; i++) { items.count()); oc.add(items[i]); } lst.clear(); }); } } }
edit: need view every piece of data? there going overhead when using lock. if you're getting data quicker speed of how fast can render it, you'll backed and/or have large collection render, might cause problems. suggest filtering draw last x number of items (say 100). also, i'm not sure why need if (dispatcher.hasthreadaccess)
condition either.
try following:
public async void additem<t>(observablecollection<t> oc, list<t> items) { // "lst" reference locked here, wasn't locked in event handler lock (items) { // change want const int maxsize = 100; // make sure doesn't index out of bounds int startindex = math.max(0, items.count - maxsize); int length = items.count - startindex; list<t> itemstorender = items.getrange(startindex, length); // can clear here in background thread. references objects // in itemstorender list. lst.clear(); // dispatcher.runasync(coredispatcherpriority.low, () => // please verify correct syntax dispatcher.run(() => { // @ second look, might need locked // edit: add overhead it's not running async. // can remove lock lock(oc) { oc.clear(); (int = 0; < itemstorender.count; i++) { // didn't notice before, why checking count again? // items.count()); oc.add(itemstorender[i]); } } }); } }
edit2: since additem method on background thread, don't think need run dispatcher.runasync. instead, think might desirable block don't end multiple calls section of code. try using dispatcher.run instead. i've updated code example above show changes. shouldn't need lock on oc anymore since lock on items enough. also, verify syntax dispatcher.run correct.
Comments
Post a Comment