Multithreading
[Link]
BackgroundWorker
BackgroundWorker
g isahelperclassinthe
p
[Link] namespaceformanaginga
workerthread.
A"cancel"flagforsignalingaworkertoendwithout
usingAbort
Astandardprotocolforreporting progress,completion
progress completion
andcancellation
AnimplementationofIComponent allowingitbesited
i h Vi lS di D i
intheVisualStudioDesigner
Exceptionhandlingontheworkerthread
TheabilitytoupdateWindowsFormscontrolsin
responsetoworkerprogressorcompletion.
Control Invoke
[Link]
InamultithreadedWindowsFormsapplication,it's
Inamulti threadedWindowsFormsapplication,it s
illegaltocallamethodorpropertyonacontrolfrom
anythreadotherthantheonethatcreatedit.
Allcrossthreadcallsmustbeexplicitlymarshalled
tothethreadthatcreatedthecontrol(usuallythe
mainthread),[Link] or
[Link] method.
TheBackgroundWorker classwrapsworkerthreads
thatneedtoreportprogressandcompletion,and
[Link] asrequired.
ThreadPool
TheBackgroundWorker classusesthe thread
threadpool,
pool,
whichrecyclesthreadstoavoidrecreatingthemfor
eachnewtask.
ThismeansoneshouldnevercallAbort ona
BackgroundWorker thread.
UsingtheBackgroundWorker
InstantiateBackgroundWorker,andhandlethe
DoWork event.
event
CallRunWorkerAsync,optionallywithanobject
argument.
argument
Handlethereportingevents forprogress,
completionandcancellation
e Argument
[Link]
AnyargumentpassedtoRunWorkerAsync
y g p y willbeforwarded
toDoWork's eventhandler,viatheeventargument's
Argumentproperty.
private void bw1_DoWork(object sender,
DoWorkEventArgs e)
[Link] isoftypeSystemObject.
Thereforeonecanpassanynumberofargumentspackedin
p y g p
aclass,structureorarray.
RunWorkerCompleted
TheRunWorkerCompleted eventfiresafterthe
DoWork eventhandlerhasdoneitsjob.
HandlingRunWorkerCompleted isnotmandatory,
isnotmandatory
butoneusuallydoessoinordertoqueryany
exception thatwasthrowninDoWork.
CodewithinaRunWorkerCompleted eventhandler
isabletoupdateWindowsFormscontrolswithout
explicitmarshalling;codewithintheDoWork event
handlercannot.
ProgressReporting
1. SettheWorkerReportsProgress
p g property
p p y totrue.
2. PeriodicallycallReportProgress fromwithintheDoWork
eventhandlerwitha"percentagecomplete"value,and
optionally,auserstateobject.
3. HandletheProgressChanged event,quering itsevent
argument'sProgressPercentage
argument sProgressPercentage property.
property
CodeintheProgressChanged eventhandlerisfreeto
interactwithUIcontrolsjustaswithRunWorkerCompleted.
Thisistypicallywhereyouwillupdateaprogressbar.
CancellationSupport
Set
SettheWorkerSupportsCancellation
t e o e Suppo tsCa ce at o p propertytotrue.
ope ty to t ue
PeriodicallychecktheCancellationPending property
fromwithintheDoWork eventhandler iftrue,setthe
eventargument'sCancelpropertytrue,andreturn.
(TheworkercansetCanceltrueandexitwithout
promptingviaCancellationPending ifitdecidesthe
job'stoodifficultanditcan'tgoon).
[Link] intheRunWorkerCompleted event
handler.
CallCancelAsync torequestcancellation.
Subclassing BackgroundWorker
BackgroundWorker isnotsealed!
ItprovidesavirtualOnDoWork method.
Whenwritingapotentiallylong
Whenwritingapotentiallylongrunningmethod
runningmethod,
onecanwriteaversionreturningasubclassed
BackgroundWorker.
g
Preconfiguredtoperformthejobasynchronously.
Theconsumerthenonlyneedstohandlethe
e co su e t e o y eeds to a d e t e
RunWorkerCompleted andProgressChanged
events.
Resources
CourseHomepage:
[Link]/teaching/ss2007/251029000
ExerciseMaterial:
[Link]/personal/[Link]
public class Client {
Dictionary <string,int> GetFinancialTotals (int
foo, int bar) { ... }
...
}
public class Client {
public FinancialWorker GetFinancialTotalsBackground
(int foo, int bar) {
return new FinancialWorker (foo, bar);
}
}
public class FinancialWorker : BackgroundWorker {
public Dictionary <string,int> Result; // We can add
typed fields.
public volatile int Foo, Bar; // We could even
expose them
// via
properties with locks!
public
bli FinancialWorker()
Fi i lW k () {
WorkerReportsProgress = true;
WorkerSupportsCancellation = true;
}
public FinancialWorker (int foo, int bar) : this() {
[Link] = foo; [Link] = bar;
}
protected override void OnDoWork (DoWorkEventArgs e) {
ReportProgress (0,
(0 "Working hard on this report
report...");
");
Initialize financial report data
while (!finished report ) {
if (CancellationPending) {
[Link] = true;
return;
}
Perform another calculation step
ReportProgress (percentCompleteCalc, "Getting
there...");
}
ReportProgress (100, "Done!");
[Link] = Result = completed report data;
}
}
GetFinancialTotalsBackground
WhoevercallsGetFinancialTotalsBackground then
getsaFinancialWorker awrappertomanagethe
[Link]
canreportprogress,becancelled,andiscompatible
[Link]'s
alsoexceptionhandled,andusesastandard
l ti h dl d d t d d
protocol(incommonwiththatofanyoneelseusing
BackgroundWorker!)