You are on page 1of 17

Multithreading

ThomasJ.Fuchs
BackgroundWorker
BackgroundWorker
g isahelperclassinthe
p
System.ComponentModel 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
Control.Invoke
InamultithreadedWindowsFormsapplication,it's
Inamulti threadedWindowsFormsapplication,it s
illegaltocallamethodorpropertyonacontrolfrom
anythreadotherthantheonethatcreatedit.
Allcrossthreadcallsmustbeexplicitlymarshalled
tothethreadthatcreatedthecontrol(usuallythe
mainthread),usingtheControl.Invoke or
Control.BeginInvoke method.
TheBackgroundWorker classwrapsworkerthreads
thatneedtoreportprogressandcompletion,and
automaticallycallsControl.Invoke 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
e.Argument
AnyargumentpassedtoRunWorkerAsync
y g p y willbeforwarded
toDoWork's eventhandler,viatheeventargument's
Argumentproperty.
private void bw1_DoWork(object sender,
DoWorkEventArgs e)

e.Argument 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).
Checke.Cancelled 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:
se.inf.ethz.ch/teaching/ss2007/251029000

ExerciseMaterial:
www.inf.ethz.ch/personal/thomas.fuchs
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() {


this.Foo = foo; this.Bar = 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) {
e.Cancel = true;
return;
}
Perform another calculation step
ReportProgress (percentCompleteCalc, "Getting
there...");
}
ReportProgress (100, "Done!");
e.Result = Result = completed report data;
}
}
GetFinancialTotalsBackground
WhoevercallsGetFinancialTotalsBackground then
getsaFinancialWorker awrappertomanagethe
backgroundoperationwithrealworldusability.It
canreportprogress,becancelled,andiscompatible
withWindowsFormswithoutControl.Invoke.It's
alsoexceptionhandled,andusesastandard
l ti h dl d d t d d
protocol(incommonwiththatofanyoneelseusing
BackgroundWorker!)

You might also like