c# - Error loading custom user controls from different threads -
i have wpf project , main window creating , loading bunch of user controls, there large data loading in background , updating built-in control throw dispatcher, works fine, problem of user controls loads lot of data, example first thing load in main area of main window, want put loading label instead, load main window fast possible user see label , run in background creation of user control , when done add child of main container area on main window while remove loading label, if follow same philosophy run same error when run task , try update window without using dispatcher. want able of create user control asynchronous update main window.
code:
user control:
public partial class customusercontrolgallery : usercontrol { public customusercontrolgallery() { initializecomponent(); } ... }
on backend class of main window:
public partial class mainwindow : window { customusercontrolgallery _customusercontrolgallery; public mainwindow() { initializecomponent(); task t = new task({ //can't use _customusercontrolgallery's dispatcher because object uninitialized , this.dispatcher not working either. _customusercontrolgallery = new customusercontrolgallery(); //error here. _gridcontainer.dispatcher.invoke(new action(() => _gridcontainer.children.add(_customusercontrolgallery))); _loadinglabel.visbility = visibility.collapse; }); t.start(); } ... }
i don't know how handle situation thread associated user control , main thread.
error:
{"the calling thread must sta, because many ui components require this."}
you're doing wrong. controls must created & operate on ui thread. said, can use backgroundworker
class load data.
you typically disabling control data being loaded in background or hiding & displaying progress indicator in place. then, start backgroundworker
. can communicate how far along using reportprogress
method. finally, when it's finished running, runworkercompleted
event fired, , use either enable control, or hide progress indicator & show control.
some quick & dirty (untested) code:
place in initialize() or control constructor:
private backgroundworker loaddata = new backgroundworker(); loaddata.dowork += loaddata_dowork; loaddata.progresschanged += loaddata_progresschanged; // if going report progress loaddata.workerreportsprogress = true; loaddata.workersupportscancellation = false; // can set true if provide cancel button loaddata.runworkercompleted += loaddata_runworkercompleted; private void dowork( object sender, doworkeventargs e ) { backgroundworker worker = sender backgroundworker; bool done = false; while ( !done ) { // if want check cancellation, include if statement if ( worker.cancellationpending ) { e.cancel = true; return; } // code load data goes here. // if wish display progress updates, compute how far along , call reportprogress here. } } private void loaddata_progresschanged( object sender, progresschangedeventargs e ) { // code report progress goes here. } private void loaddata_runworkercompleted( object sender, runworkercompletedeventargs e ) { // code whatever necessary put ui completed state goes here. }
Comments
Post a Comment