c# - CrossThreading issue with BackgroundWorker and statusstrip update -
i have been working on tool uses backgroundworker perform ping operation on regular interval. running issue backgroundworker progresschanged event. code progresschanged event below:
private void backgroundworker1_progresschanged(object sender, progresschangedeventargs e) { progressupdated update = (progressupdated)e.userstate; if (sender.tostring() == "system.componentmodel.backgroundworker") { toolstripstatuslabel1.text = update.generalstatus; toolstripprogressbar1.value = update.progressstatus; toolstripstatuslabel2.text = update.specificstatus; } else { toolstripstatuslabel1.text = update.generalstatus; toolstripprogressbar2.value = update.progressstatus; toolstripstatuslabel3.text = update.specificstatus; } }
the progresschanged event gets called both in backgroundwork updates first values , pingcompletedcallback event when ping finishes. run cross threading issue when progresschanged event runs pingcompletedcallback event. throws error when goes update second progress bar.
i can not seem figure out why happening 1 of calls not other.
is pingcompletedcallback happening on backgroundworker thread , thats why causing cross threading issues?
if how raise event processed on ui thread , not backgroundworker?
edit:
private void backgroundworker1_dowork(object sender, doworkeventargs e) { backgroundworker worker = sender backgroundworker; // creates ping , sends async progressupdated args = new progressupdated(string1, int1, string 2); worker.reportprogress(0,args); // rest of thread cleanup when cancellation called } private void pingcompletedcallback(object sender, pingcompletedeventargs e) { // handle ping response progressupdated update = new progressupdated(string1, int1, string2); progresschangedeventargs changed = new progresschangedeventargs(1,update); backgroundworker1_progresschanged(this, changed); // handle other types of responses }
i thought use of events allow separation of threads. aka worker thread raises event ui thread listening for, raised event gets processed on ui thread.
since understanding wrong, pingcompletedcallback have access the reportprogress method of backgroundworker?
i change in pingcompletedcallback:
progresschangedeventargs changed = new progresschangedeventargs(1,update); backgroundworker1_progresschanged(this, changed);
to:
backgroundworker1.reportprogress(1, update);
or need change in other way?
thanks anyone's assistance.
edit 2:
changed progrsschanged event
private void backgroundworker1_progresschanged(object sender, progresschangedeventargs e) { progressupdated update = (progressupdated)e.userstate; toolstripstatuslabel1.text = update.generalstatus; toolstripprogressbar1.value = update.progressstatus; toolstripstatuslabel2.text = update.specificstatus; }
i created second update event
private void pingupdate (object sender, progressupdated e) { toolstripstatuslabel1.text = e.generalstatus; toolstripprogressbar2.value = e.progressstatus; toolstripstatuslable3.text = e.sepcificstatus; }
the thing have left call new event pingcompletedcallback in such way gets executed on ui thread. invoke statement used or should invokes used in new event?
the documentation backgroundworker states should not manipulating ui objects through dowork method, , changes ui objects should made through reportprogress. haven't looked @ reflector, it's performing hidden "invoke" you. whatever raising pingcompleted
event executing within worker thread or other thread not main thread.
you see in threads window of visual studio debugger dotask
not execute on main thread; however, when reportprogress
called, handler executed on main thread. since controls created on main thread, not see exception.
now, if attempt call backgroundworker1_progresschanged
explicitly within dowork method, backgroundworker1_progressedchanged
executed on same thread that's executing dowork method, or, in case, method that's raising pingcompleted
event:
you can solve cross thread exception adding invokerequired checks within backgroundworker1_progresschanged
handler, or route pingcompleted handler call reportprogress
edit:
calling reportprogress
pingcompleted
handler won't work because lose original sender.
private void backgroundworker1_progresschanged(object sender, progresschangedeventargs e) { if (invokerequired) { invoke(new progresschangedeventhandler(backgroundworker1_progresschanged), sender, e); return; } // rest of code goes here }
edit 2 response:
private void pingupdate (object sender, progressupdated e) { if (invokerequired) { invoke(new action<object, progressupdated>(pingupdate), sender, e); return; } toolstripstatuslabel1.text = e.generalstatus; toolstripprogressbar2.value = e.progressstatus; toolstripstatuslable3.text = e.sepcificstatus; }
Comments
Post a Comment