c# - Modifying a list from another thread in WPF? -
i have wpf application mainwindow handling output of messages. i've set list of messages in window this:
public partial class mainwindow : window { public concurrentbag<viewmessage> messagelist { { return (concurrentbag<viewmessage>)getvalue(messagelistproperty); } set { setvalue(messagelistproperty, value); } } public static readonly dependencyproperty messagelistproperty = dependencyproperty.register("messagelist", typeof(concurrentbag<viewmessage>), typeof(mainwindow), new propertymetadata(null)); public mainwindow() { initializecomponent(); } public void showmessage(string header, string message) { viewmessage message = new viewmessage("sucess", "example message"); messagelist.add(message); } }
the style of messages set fade out after time (3 seconds), , want remove item collection after time. don't know if it's possible in xaml only, if is, how do it?
i tried doing programatically this:
public mainwindow() { timer timer = new timer(); timer.interval = 1000; timer.elapsed += new elapsedeventhandler(messagechecktick); timer.start(); //tried thread.start() } private void messagechecktick(object sender, elapsedeventargs e) { (int = messagelist.count - 1; >= 0; i++) { viewmessage message = null; if (messagelist.trypeek(out message)) { if (message.datemessage >= datetime.now.addmilliseconds(3000)) { messagelist.trytake(out message); } } } }
but errors of the calling thread cannot access object because different thread owns it
. tried solutions of similar questions in so, adding concurrentbag or using dispatcher
, didn't work. in case of dispatcher
can't call thread.sleep
since it's main thread of program.
how can make work?
dispatchertimer
great idea. write handler akin this:
// remove outdated var dtthreshold = datetime.now.addseconds(-3); foreach (var el in _localobservable.where(i => i.datemessage < dtthreshold).tolist()) _localobservable.remove(el); // add new viewmessage message = null; while (messagelist.trytake(out message)) _localobservable.add(message);
the observable collection must manipulated ui thread – therefore need keep concurrentbag (to add elements non-ui thread).
few things note:
.tolist() in remove section: ensures to-be-removed candidates determined before first of them removed (in case, enumeration of _localobservable ends before it's modified)
no need
trypeek
in advance -trytake
take element , remove bag, giving element.
if don't use concurrentbag each add
operation must posted ui thread. big number of add
events may pollute ui thread, making slow & inefficient.
Comments
Post a Comment