SlideShare a Scribd company logo
Mohammad Shaker 
mohammadshaker.com 
@ZGTRShaker 
2011, 2012, 2013, 2014 
C# Advanced 
L04-THREADING
Threading
Concept of Threading 
•What is a “Thread”? 
–The advantage of threading is the ability to create applications that use more than one thread of execution. For example, a process can have a user interface thread that manages interactions with the user and worker threads that perform other tasks while the user interface thread waits for user input. 
•What’s this? 
for (int i = 1; i < 50; i++) 
{ 
Console.SetWindowSize(i, i); 
System.Threading.Thread.Sleep(50); 
}
Let’s Parallel
Let’s Parallel 
class Program 
{ 
private static void Main() 
{ 
for (int i = 0; i < 10; i++) 
{ 
long total = GetTotal(); 
Console.WriteLine("{0} -{1}", i, total); 
} 
} 
private static long GetTotal() 
{ 
long total = 0; 
for (inti= 1; i< 100000000; i++) 
{ 
total += i; 
} 
return total; 
} 
}
Let’s Parallel 
class Program 
{ 
private static void Main() 
{ 
for (int i = 0; i < 10; i++) 
{ 
long total = GetTotal(); 
Console.WriteLine("{0} -{1}", i, total); 
} 
} 
private static long GetTotal() 
{ 
long total = 0; 
for (inti= 1; i< 100000000; i++) 
{ 
total += i; 
} 
return total; 
} 
} 
0 -4999999950000000 
1 -4999999950000000 
2 -4999999950000000 
3 -4999999950000000 
4 -4999999950000000 
5 -4999999950000000 
6 -4999999950000000 
7 -4999999950000000 
8 -4999999950000000 
9 -4999999950000000 
Press any key to continue . . .
Let’s Parallel 
class Program 
{ 
private static void Main() 
{ 
for (int i = 0; i < 10; i++) 
{ 
long total = GetTotal(); 
Console.WriteLine("{0} -{1}", i, total); 
} 
} 
private static long GetTotal() 
{ 
long total = 0; 
for (inti= 1; i< 100000000; i++) 
{ 
total += i; 
} 
return total; 
} 
}
Let’s Parallel 
class Program 
{ 
private static void Main() 
{ 
Parallel.For(0, 10, i => 
{ 
long total = GetTotal(); 
Console.WriteLine("{0} -{1}", i, total); 
}); 
} 
private static long GetTotal() 
{ 
long total = 0; 
for (inti= 1; i< 100000000; i++) 
{ 
total += i; 
} 
return total; 
} 
}
Let’s Parallel 
class Program 
{ 
private static void Main() 
{ 
Parallel.For(0, 10, i => 
{ 
long total = GetTotal(); 
Console.WriteLine("{0} -{1}", i, total); 
}); 
} 
private static long GetTotal() 
{ 
long total = 0; 
for (inti= 1; i< 100000000; i++) 
{ 
total += i; 
} 
return total; 
} 
} 
0 -4999999950000000 
1 -4999999950000000 
2 -4999999950000000 
3 -4999999950000000 
4 -4999999950000000 
5 -4999999950000000 
6 -4999999950000000 
7 -4999999950000000 
8 -4999999950000000 
9 -4999999950000000 
Press any key to continue . . . 
The Same Result but Much Faster
Parallel Task
Let’s Parallel 
0 on Task 1 
2 on Task 1 
5 on Task 2 
10 on Task 3 
1 on Task 5 
4 on Task 5 
8 on Task 5 
15 on Task 4 
16 on Task 4 
17 on Task 4 
18 on Task 4 
19 on Task 4 
13 on Task 4 
14 on Task 4 
6 on Task 2 
7 on Task 2 
9 on Task 5 
11 on Task 3 
12 on Task 3 
3 on Task 1 
Press any key to continue . . . 
private void Test() 
{ 
Parallel.For(0, 20, i=> Console.WriteLine("{0} on Task {1}", i, Task.CurrentId)); 
} 
5different tasks working
Let’s Parallel 
0 on Task 1 
2 on Task 1 
5 on Task 2 
10 on Task 3 
1 on Task 5 
4 on Task 5 
8 on Task 5 
15 on Task 4 
16 on Task 4 
17 on Task 4 
18 on Task 4 
19 on Task 4 
13 on Task 4 
14 on Task 4 
6 on Task 2 
7 on Task 2 
9 on Task 5 
11 on Task 3 
12 on Task 3 
3 on Task 1 
Press any key to continue . . . 
private void Test() 
{ 
Parallel.For(0, 20, i=> Console.WriteLine("{0} on Task {1}", i, Task.CurrentId)); 
} 
0 on Task 1 
2 on Task 1 
5 on Task 2 
6 on Task 2 
10 on Task 3 
11 on Task 3 
12 on Task 3 
13 on Task 3 
14 on Task 3 
16 on Task 3 
3 on Task 1 
15 on Task 4 
8 on Task 4 
9 on Task 4 
7 on Task 2 
1 on Task 5 
17 on Task 3 
4 on Task 1 
18 on Task 3 
19 on Task 3 
Press any key to continue . . . 
0 on Task 1 
1 on Task 1 
5 on Task 2 
6 on Task 2 
7 on Task 2 
8 on Task 2 
9 on Task 2 
11 on Task 2 
12 on Task 2 
13 on Task 2 
15 on Task 4 
16 on Task 4 
17 on Task 4 
18 on Task 4 
19 on Task 4 
2 on Task 1 
4 on Task 4 
14 on Task 2 
10 on Task 3 
3 on Task 5 
Press any key to continue . . .
Let’s Parallel 
•The following: 
•Is the same as: 
private void Test() 
{ 
Parallel.For(0, 20, i=> 
{ 
Console.WriteLine("{0} on Task {1}", i, Task.CurrentId); 
}); 
} 
private void Test() 
{ 
Parallel.For(0, 20, i=> Console.WriteLine("{0} on Task {1}", i, Task.CurrentId)); 
}
Let’s Parallel 
0 on Task 1 
1 on Task 1 
2 on Task 1 
3 on Task 1 
4 on Task 1 
5 on Task 1 
6 on Task 1 
7 on Task 1 
8 on Task 1 
10 on Task 2 
11 on Task 2 
12 on Task 2 
13 on Task 2 
14 on Task 2 
15 on Task 2 
16 on Task 2 
9 on Task 1 
17 on Task 2 
18 on Task 2 
19 on Task 2 
Press any key to continue . . . 
ParallelOptionsparallelOptions= new ParallelOptions(); 
parallelOptions.MaxDegreeOfParallelism= 2; 
Parallel.For(0, 20, parallelOptions, i=> 
{ 
Console.WriteLine("{0} on Task {1}", i, Task.CurrentId); 
}); 
0 on Task 1 
1 on Task 1 
2 on Task 1 
3 on Task 1 
4 on Task 1 
10 on Task 2 
11 on Task 2 
12 on Task 2 
13 on Task 2 
14 on Task 2 
15 on Task 2 
16 on Task 2 
17 on Task 2 
18 on Task 2 
19 on Task 2 
7 on Task 2 
8 on Task 2 
9 on Task 2 
5 on Task 1 
6 on Task 1 
Press any key to continue . . . 
Limiting the number of tasks to just 2
Parallel.Invoke
Parallel.Invoke 
static void Main() 
{ 
Parallel.Invoke( 
() => RunTask(1), 
() => RunTask(2), 
() => RunTask(3), 
() => RunTask(4), 
() => RunTask(5) 
); 
} 
static void RunTask(inttaskNumber) 
{ 
Console.WriteLine("Task {0} started", taskNumber); 
Console.WriteLine("Task {0} complete", taskNumber); 
}
Parallel.Invoke 
static void Main() 
{ 
Parallel.Invoke( 
() => RunTask(1), 
() => RunTask(2), 
() => RunTask(3), 
() => RunTask(4), 
() => RunTask(5) 
); 
} 
static void RunTask(inttaskNumber) 
{ 
Console.WriteLine("Task {0} started", taskNumber); 
Console.WriteLine("Task {0} complete", taskNumber); 
} 
Task 2 started 
Task 2 complete 
Task 3 started 
Task 4 started 
Task 1 started 
Task 1 complete 
Task 3 complete 
Task 5 started 
Task 5 complete 
Task 4 complete 
Press any key to continue . . .
Parallel.Invoke 
static void Main() 
{ 
Parallel.Invoke( 
() => RunTask(1), 
() => RunTask(2), 
() => RunTask(3), 
() => RunTask(4), 
() => RunTask(5) 
); 
} 
static void RunTask(inttaskNumber) 
{ 
Console.WriteLine("Task {0} started", taskNumber); 
Console.WriteLine("Task {0} complete", taskNumber); 
} 
Task 2 started 
Task 2 complete 
Task 3 started 
Task 4 started 
Task 1 started 
Task 1 complete 
Task 3 complete 
Task 5 started 
Task 5 complete 
Task 4 complete 
Press any key to continue . . . 
Use the following to limit the number of concurrent tasks: 
ParallelOptionsparallelOptions= new ParallelOptions(); 
parallelOptions.MaxDegreeOfParallelism= 2;
Threading Problems, like,
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
static void SubtractOne() 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
}
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
static void SubtractOne() 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
Incremented counter to 1. 
Decremented counter to -1. 
Final counter value is -1.
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
static void SubtractOne() 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
Incremented counter to 1. 
Decremented counter to -1. 
Final counter value is -1.
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
static void SubtractOne() 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
Incremented counter to 1. 
Decremented counter to -1. 
Final counter value is -1. 
Race Conditions
Racing ConditionsThe Solution
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
static void SubtractOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
} 
Race Conditions
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
static void SubtractOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
} 
Race Conditions 
New
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
static void SubtractOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
} 
Race Conditions 
Shared object
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
static void SubtractOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
} 
Race Conditions 
Locking the shared object for each thread
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
static void SubtractOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
} 
The right output 
Incremented counter to 1. 
Decremented counter to 0. 
Final counter value is 0.
Lock (Object)
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
static void SubtractOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
} 
Not good, don’t do this, or lock a string or etc.
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
static void Main(string[] args) 
{ 
Parallel.Invoke(AddOne, 
SubtractOne); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp++; 
Thread.Sleep(2000); 
Console.WriteLine("Incremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
static void SubtractOne() 
{ 
lock (_lock) 
{ 
inttemp = _counter; 
temp--; 
Thread.Sleep(2000); 
Console.WriteLine("Decremented counter to {0}.", temp); 
_counter = temp; 
} 
} 
} 
The best choice for a locking object is a private or protected object defined within the class that controls the shared state.
ThreadClass
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
constintsleepAmount= 500; 
static void Main(string[] args) 
{ 
Thread tAdd= new Thread(AddOne); 
Thread tSub= new Thread(SubtractOne); 
tAdd.Start(); 
tSub.Start(); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter++; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Incremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
static void SubtractOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter--; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Decremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
} 
}
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
constintsleepAmount= 500; 
static void Main(string[] args) 
{ 
Thread tAdd= new Thread(AddOne); 
Thread tSub= new Thread(SubtractOne); 
tAdd.Start(); 
tSub.Start(); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter++; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Incremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
static void SubtractOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter--; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Decremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
} 
} 
Monitor Lock
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
constintsleepAmount= 500; 
static void Main(string[] args) 
{ 
Thread tAdd= new Thread(AddOne); 
Thread tSub= new Thread(SubtractOne); 
tAdd.Start(); 
tSub.Start(); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter++; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Incremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
static void SubtractOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter--; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Decremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
} 
} 
Acquire Lock
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
constintsleepAmount= 500; 
static void Main(string[] args) 
{ 
Thread tAdd= new Thread(AddOne); 
Thread tSub= new Thread(SubtractOne); 
tAdd.Start(); 
tSub.Start(); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter++; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Incremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
static void SubtractOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter--; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Decremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
} 
} 
Release Lock
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
constintsleepAmount= 500; 
static void Main(string[] args) 
{ 
Thread tAdd= new Thread(AddOne); 
Thread tSub= new Thread(SubtractOne); 
tAdd.Start(); 
tSub.Start(); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter++; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Incremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
static void SubtractOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter--; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Decremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
} 
} 
Final counter value is 0. 
Incremented counter to 1. 
Decremented counter to 0. 
Press any key to continue . . .
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
constintsleepAmount= 500; 
static void Main(string[] args) 
{ 
Thread tAdd= new Thread(AddOne); 
Thread tSub= new Thread(SubtractOne); 
tAdd.Start(); 
tSub.Start(); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter++; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Incremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
static void SubtractOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter--; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Decremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
} 
} 
Final counter value is 0. 
Incremented counter to 1. 
Decremented counter to 0. 
Press any key to continue . . . 
Why?
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
constintsleepAmount= 500; 
static void Main(string[] args) 
{ 
Thread tAdd= new Thread(AddOne); 
Thread tSub= new Thread(SubtractOne); 
tAdd.Start(); 
tSub.Start(); 
tAdd.Join(); 
tSub.Join(); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter++; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Incremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
static void SubtractOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter--; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Decremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
} 
} 
Blocks the calling thread until the thread terminates
Threading Problems 
class Program 
{ 
static int_counter = 0; 
static object _lock = new object(); 
constintsleepAmount= 500; 
static void Main(string[] args) 
{ 
Thread tAdd= new Thread(AddOne); 
Thread tSub= new Thread(SubtractOne); 
tAdd.Start(); 
tSub.Start(); 
tAdd.Join(); 
tSub.Join(); 
Console.WriteLine("Final counter value is {0}.", _counter); 
} 
static void AddOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter++; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Incremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
static void SubtractOne() 
{ 
Monitor.Enter(_lock); 
try 
{ 
_counter--; 
Thread.Sleep(sleepAmount); 
Console.WriteLine("Decremented counter to {0}.", _counter); 
} 
finally { Monitor.Exit(_lock); } 
} 
} 
} 
Incremented counter to 1. 
Decremented counter to 0. 
Final counter value is 0. 
Press any key to continue . . . 
Blocks the calling thread until the thread terminates
Task.Factory 
varmyTask= Task.Factory.StartNew(() => { return "Hello, world!"; }); 
Console.WriteLine(myTask.Result);
TastWait
Wait 
int[] values = null; 
Task loadDataTask= new Task(() => 
{ 
Console.WriteLine("Loading data..."); 
Thread.Sleep(5000); 
values = Enumerable.Range(1,10).ToArray(); 
}); 
loadDataTask.Start(); 
Console.WriteLine("Data total = {0}", values.Sum());
Wait 
int[] values = null; 
Task loadDataTask= new Task(() => 
{ 
Console.WriteLine("Loading data..."); 
Thread.Sleep(5000); 
values = Enumerable.Range(1,10).ToArray(); 
}); 
loadDataTask.Start(); 
Console.WriteLine("Data total = {0}", values.Sum()); 
Will throw ArgumentNullExceptionbecause we are trying to use the array before it has been populated by the parallel task.
Wait 
int[] values = null; 
Task loadDataTask= new Task(() => 
{ 
Console.WriteLine("Loading data..."); 
Thread.Sleep(5000); 
values = Enumerable.Range(1,10).ToArray(); 
}); 
loadDataTask.Start(); 
Console.WriteLine("Data total = {0}", values.Sum()); 
Will throw ArgumentNullExceptionbecause we are trying to use the array before it has been populated by the parallel task. 
int[] values = null; 
Task loadDataTask= new Task(() => 
{ 
Console.WriteLine("Loading data..."); 
Thread.Sleep(5000); 
values = Enumerable.Range(1,10).ToArray(); 
}); 
loadDataTask.Start(); 
loadDataTask.Wait(); 
loadDataTask.Dispose(); 
Console.WriteLine("Data total = {0}", values.Sum()); // Data total = 55
int[] values = null; 
Task loadDataTask= new Task(() => 
{ 
Console.WriteLine("Loading data..."); 
Thread.Sleep(5000); 
values = Enumerable.Range(1,10).ToArray(); 
}); 
loadDataTask.Start(); 
loadDataTask.Wait(); 
loadDataTask.Dispose(); 
Console.WriteLine("Data total = {0}", values.Sum()); // Data total = 55 
Wait 
int[] values = null; 
Task loadDataTask= new Task(() => 
{ 
Console.WriteLine("Loading data..."); 
Thread.Sleep(5000); 
values = Enumerable.Range(1,10).ToArray(); 
}); 
loadDataTask.Start(); 
Console.WriteLine("Data total = {0}", values.Sum()); 
To fix it, we will now waitfor the task to be done
int[] values = null; 
Task loadDataTask= new Task(() => 
{ 
Console.WriteLine("Loading data..."); 
Thread.Sleep(5000); 
values = Enumerable.Range(1,10).ToArray(); 
}); 
loadDataTask.Start(); 
loadDataTask.Wait(); 
loadDataTask.Dispose(); 
Console.WriteLine("Data total = {0}", values.Sum()); 
Wait 
int[] values = null; 
Task loadDataTask= new Task(() => 
{ 
Console.WriteLine("Loading data..."); 
Thread.Sleep(5000); 
values = Enumerable.Range(1,10).ToArray(); 
}); 
loadDataTask.Start(); 
Console.WriteLine("Data total = {0}", values.Sum()); 
The output will be Data total = 55
Tasks Continuation 
Task continuation = firstTask.ContinueWith(antecedent => { /* functionality */ });

More Related Content

PDF
54240326 copy
PDF
ReactiveCocoa workshop
PDF
Gevent be or not to be
PDF
The Future of Futures - A Talk About Java 8 CompletableFutures
PPTX
Unit testing patterns for concurrent code
PDF
Mutation @ Spotify
PDF
The Ring programming language version 1.9 book - Part 48 of 210
ODP
Concurrent Programming in Java
54240326 copy
ReactiveCocoa workshop
Gevent be or not to be
The Future of Futures - A Talk About Java 8 CompletableFutures
Unit testing patterns for concurrent code
Mutation @ Spotify
The Ring programming language version 1.9 book - Part 48 of 210
Concurrent Programming in Java

What's hot (17)

PPTX
CSharp for Unity Day2
PDF
GenServer in action
PPTX
The secret unit testing tools no one ever told you about
PPTX
Tools and Techniques for Understanding Threading Behavior in Android*
PDF
Completable future
PDF
The Ring programming language version 1.6 book - Part 7 of 189
PPTX
From clever code to better code
PPTX
Java весна 2013 лекция 2
PDF
The Ring programming language version 1.6 book - Part 184 of 189
PDF
Leveraging Completable Futures to handle your query results Asynchrhonously
PDF
Actor Concurrency
PDF
The Ring programming language version 1.7 book - Part 85 of 196
PDF
STAMP Descartes Presentation
PDF
The Ring programming language version 1.8 book - Part 32 of 202
PDF
Java 7 LavaJUG
PDF
The Ring programming language version 1.8 book - Part 88 of 202
PDF
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
CSharp for Unity Day2
GenServer in action
The secret unit testing tools no one ever told you about
Tools and Techniques for Understanding Threading Behavior in Android*
Completable future
The Ring programming language version 1.6 book - Part 7 of 189
From clever code to better code
Java весна 2013 лекция 2
The Ring programming language version 1.6 book - Part 184 of 189
Leveraging Completable Futures to handle your query results Asynchrhonously
Actor Concurrency
The Ring programming language version 1.7 book - Part 85 of 196
STAMP Descartes Presentation
The Ring programming language version 1.8 book - Part 32 of 202
Java 7 LavaJUG
The Ring programming language version 1.8 book - Part 88 of 202
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Ad

Viewers also liked (17)

PDF
Threading in c#
PPTX
Threading
PPTX
PPTX
Threading in C#
PPT
Threads c sharp
PPTX
Multi threading design pattern
PDF
Real time web
PPS
07 iec t1_s1_oo_ps_session_10
PPT
Threads c sharp
PPT
Intro To .Net Threads
PPTX
PPTX
Multithreading Design Patterns
PDF
C# Delegates and Event Handling
PPTX
Delegates and events
ODP
Multithreading 101
PDF
Multithreading done right
Threading in c#
Threading
Threading in C#
Threads c sharp
Multi threading design pattern
Real time web
07 iec t1_s1_oo_ps_session_10
Threads c sharp
Intro To .Net Threads
Multithreading Design Patterns
C# Delegates and Event Handling
Delegates and events
Multithreading 101
Multithreading done right
Ad

Similar to C# Advanced L04-Threading (20)

PPTX
Flow Control and Exception Handling.pptx
PPT
C Sharp Jn (3)
DOCX
.net progrmming part1
PPTX
Python programming workshop session 2
PDF
04-Looping( For , while and do while looping) .pdf
PPT
Loops
PDF
The output should now look like this Row 1 sum 30 Row 2 sum.pdf
PPTX
MUST CS101 Lab11
PDF
soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
PPTX
C# Loops
DOCX
Parallel Programming With Dot Net
PDF
C++ L03-Control Structure
PPT
Whats new in_csharp4
PDF
.NET Multithreading and File I/O
PPTX
C#.net
PDF
C++ Course - Lesson 2
PPTX
Dts x dicoding #2 memulai pemrograman kotlin
PPT
Thread
PDF
Java 7 at SoftShake 2011
KEY
Why Learn Python?
Flow Control and Exception Handling.pptx
C Sharp Jn (3)
.net progrmming part1
Python programming workshop session 2
04-Looping( For , while and do while looping) .pdf
Loops
The output should now look like this Row 1 sum 30 Row 2 sum.pdf
MUST CS101 Lab11
soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
C# Loops
Parallel Programming With Dot Net
C++ L03-Control Structure
Whats new in_csharp4
.NET Multithreading and File I/O
C#.net
C++ Course - Lesson 2
Dts x dicoding #2 memulai pemrograman kotlin
Thread
Java 7 at SoftShake 2011
Why Learn Python?

More from Mohammad Shaker (20)

PDF
12 Rules You Should to Know as a Syrian Graduate
PDF
Ultra Fast, Cross Genre, Procedural Content Generation in Games [Master Thesis]
PDF
Interaction Design L06 - Tricks with Psychology
PDF
Short, Matters, Love - Passioneers Event 2015
PDF
Unity L01 - Game Development
PDF
Android L07 - Touch, Screen and Wearables
PDF
Interaction Design L03 - Color
PDF
Interaction Design L05 - Typography
PDF
Interaction Design L04 - Materialise and Coupling
PDF
Android L05 - Storage
PDF
Android L04 - Notifications and Threading
PDF
Android L09 - Windows Phone and iOS
PDF
Interaction Design L01 - Mobile Constraints
PDF
Interaction Design L02 - Pragnanz and Grids
PDF
Android L10 - Stores and Gaming
PDF
Android L06 - Cloud / Parse
PDF
Android L08 - Google Maps and Utilities
PDF
Android L03 - Styles and Themes
PDF
Android L02 - Activities and Adapters
PDF
Android L01 - Warm Up
12 Rules You Should to Know as a Syrian Graduate
Ultra Fast, Cross Genre, Procedural Content Generation in Games [Master Thesis]
Interaction Design L06 - Tricks with Psychology
Short, Matters, Love - Passioneers Event 2015
Unity L01 - Game Development
Android L07 - Touch, Screen and Wearables
Interaction Design L03 - Color
Interaction Design L05 - Typography
Interaction Design L04 - Materialise and Coupling
Android L05 - Storage
Android L04 - Notifications and Threading
Android L09 - Windows Phone and iOS
Interaction Design L01 - Mobile Constraints
Interaction Design L02 - Pragnanz and Grids
Android L10 - Stores and Gaming
Android L06 - Cloud / Parse
Android L08 - Google Maps and Utilities
Android L03 - Styles and Themes
Android L02 - Activities and Adapters
Android L01 - Warm Up

Recently uploaded (20)

PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
history of c programming in notes for students .pptx
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Nekopoi APK 2025 free lastest update
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
top salesforce developer skills in 2025.pdf
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
Reimagine Home Health with the Power of Agentic AI​
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PPTX
ai tools demonstartion for schools and inter college
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
How Creative Agencies Leverage Project Management Software.pdf
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Navsoft: AI-Powered Business Solutions & Custom Software Development
history of c programming in notes for students .pptx
Softaken Excel to vCard Converter Software.pdf
Adobe Illustrator 28.6 Crack My Vision of Vector Design
How to Migrate SBCGlobal Email to Yahoo Easily
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
VVF-Customer-Presentation2025-Ver1.9.pptx
Nekopoi APK 2025 free lastest update
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
top salesforce developer skills in 2025.pdf
How to Choose the Right IT Partner for Your Business in Malaysia
Reimagine Home Health with the Power of Agentic AI​
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Odoo POS Development Services by CandidRoot Solutions
2025 Textile ERP Trends: SAP, Odoo & Oracle
ai tools demonstartion for schools and inter college
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
How Creative Agencies Leverage Project Management Software.pdf
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises

C# Advanced L04-Threading

  • 1. Mohammad Shaker mohammadshaker.com @ZGTRShaker 2011, 2012, 2013, 2014 C# Advanced L04-THREADING
  • 3. Concept of Threading •What is a “Thread”? –The advantage of threading is the ability to create applications that use more than one thread of execution. For example, a process can have a user interface thread that manages interactions with the user and worker threads that perform other tasks while the user interface thread waits for user input. •What’s this? for (int i = 1; i < 50; i++) { Console.SetWindowSize(i, i); System.Threading.Thread.Sleep(50); }
  • 5. Let’s Parallel class Program { private static void Main() { for (int i = 0; i < 10; i++) { long total = GetTotal(); Console.WriteLine("{0} -{1}", i, total); } } private static long GetTotal() { long total = 0; for (inti= 1; i< 100000000; i++) { total += i; } return total; } }
  • 6. Let’s Parallel class Program { private static void Main() { for (int i = 0; i < 10; i++) { long total = GetTotal(); Console.WriteLine("{0} -{1}", i, total); } } private static long GetTotal() { long total = 0; for (inti= 1; i< 100000000; i++) { total += i; } return total; } } 0 -4999999950000000 1 -4999999950000000 2 -4999999950000000 3 -4999999950000000 4 -4999999950000000 5 -4999999950000000 6 -4999999950000000 7 -4999999950000000 8 -4999999950000000 9 -4999999950000000 Press any key to continue . . .
  • 7. Let’s Parallel class Program { private static void Main() { for (int i = 0; i < 10; i++) { long total = GetTotal(); Console.WriteLine("{0} -{1}", i, total); } } private static long GetTotal() { long total = 0; for (inti= 1; i< 100000000; i++) { total += i; } return total; } }
  • 8. Let’s Parallel class Program { private static void Main() { Parallel.For(0, 10, i => { long total = GetTotal(); Console.WriteLine("{0} -{1}", i, total); }); } private static long GetTotal() { long total = 0; for (inti= 1; i< 100000000; i++) { total += i; } return total; } }
  • 9. Let’s Parallel class Program { private static void Main() { Parallel.For(0, 10, i => { long total = GetTotal(); Console.WriteLine("{0} -{1}", i, total); }); } private static long GetTotal() { long total = 0; for (inti= 1; i< 100000000; i++) { total += i; } return total; } } 0 -4999999950000000 1 -4999999950000000 2 -4999999950000000 3 -4999999950000000 4 -4999999950000000 5 -4999999950000000 6 -4999999950000000 7 -4999999950000000 8 -4999999950000000 9 -4999999950000000 Press any key to continue . . . The Same Result but Much Faster
  • 11. Let’s Parallel 0 on Task 1 2 on Task 1 5 on Task 2 10 on Task 3 1 on Task 5 4 on Task 5 8 on Task 5 15 on Task 4 16 on Task 4 17 on Task 4 18 on Task 4 19 on Task 4 13 on Task 4 14 on Task 4 6 on Task 2 7 on Task 2 9 on Task 5 11 on Task 3 12 on Task 3 3 on Task 1 Press any key to continue . . . private void Test() { Parallel.For(0, 20, i=> Console.WriteLine("{0} on Task {1}", i, Task.CurrentId)); } 5different tasks working
  • 12. Let’s Parallel 0 on Task 1 2 on Task 1 5 on Task 2 10 on Task 3 1 on Task 5 4 on Task 5 8 on Task 5 15 on Task 4 16 on Task 4 17 on Task 4 18 on Task 4 19 on Task 4 13 on Task 4 14 on Task 4 6 on Task 2 7 on Task 2 9 on Task 5 11 on Task 3 12 on Task 3 3 on Task 1 Press any key to continue . . . private void Test() { Parallel.For(0, 20, i=> Console.WriteLine("{0} on Task {1}", i, Task.CurrentId)); } 0 on Task 1 2 on Task 1 5 on Task 2 6 on Task 2 10 on Task 3 11 on Task 3 12 on Task 3 13 on Task 3 14 on Task 3 16 on Task 3 3 on Task 1 15 on Task 4 8 on Task 4 9 on Task 4 7 on Task 2 1 on Task 5 17 on Task 3 4 on Task 1 18 on Task 3 19 on Task 3 Press any key to continue . . . 0 on Task 1 1 on Task 1 5 on Task 2 6 on Task 2 7 on Task 2 8 on Task 2 9 on Task 2 11 on Task 2 12 on Task 2 13 on Task 2 15 on Task 4 16 on Task 4 17 on Task 4 18 on Task 4 19 on Task 4 2 on Task 1 4 on Task 4 14 on Task 2 10 on Task 3 3 on Task 5 Press any key to continue . . .
  • 13. Let’s Parallel •The following: •Is the same as: private void Test() { Parallel.For(0, 20, i=> { Console.WriteLine("{0} on Task {1}", i, Task.CurrentId); }); } private void Test() { Parallel.For(0, 20, i=> Console.WriteLine("{0} on Task {1}", i, Task.CurrentId)); }
  • 14. Let’s Parallel 0 on Task 1 1 on Task 1 2 on Task 1 3 on Task 1 4 on Task 1 5 on Task 1 6 on Task 1 7 on Task 1 8 on Task 1 10 on Task 2 11 on Task 2 12 on Task 2 13 on Task 2 14 on Task 2 15 on Task 2 16 on Task 2 9 on Task 1 17 on Task 2 18 on Task 2 19 on Task 2 Press any key to continue . . . ParallelOptionsparallelOptions= new ParallelOptions(); parallelOptions.MaxDegreeOfParallelism= 2; Parallel.For(0, 20, parallelOptions, i=> { Console.WriteLine("{0} on Task {1}", i, Task.CurrentId); }); 0 on Task 1 1 on Task 1 2 on Task 1 3 on Task 1 4 on Task 1 10 on Task 2 11 on Task 2 12 on Task 2 13 on Task 2 14 on Task 2 15 on Task 2 16 on Task 2 17 on Task 2 18 on Task 2 19 on Task 2 7 on Task 2 8 on Task 2 9 on Task 2 5 on Task 1 6 on Task 1 Press any key to continue . . . Limiting the number of tasks to just 2
  • 16. Parallel.Invoke static void Main() { Parallel.Invoke( () => RunTask(1), () => RunTask(2), () => RunTask(3), () => RunTask(4), () => RunTask(5) ); } static void RunTask(inttaskNumber) { Console.WriteLine("Task {0} started", taskNumber); Console.WriteLine("Task {0} complete", taskNumber); }
  • 17. Parallel.Invoke static void Main() { Parallel.Invoke( () => RunTask(1), () => RunTask(2), () => RunTask(3), () => RunTask(4), () => RunTask(5) ); } static void RunTask(inttaskNumber) { Console.WriteLine("Task {0} started", taskNumber); Console.WriteLine("Task {0} complete", taskNumber); } Task 2 started Task 2 complete Task 3 started Task 4 started Task 1 started Task 1 complete Task 3 complete Task 5 started Task 5 complete Task 4 complete Press any key to continue . . .
  • 18. Parallel.Invoke static void Main() { Parallel.Invoke( () => RunTask(1), () => RunTask(2), () => RunTask(3), () => RunTask(4), () => RunTask(5) ); } static void RunTask(inttaskNumber) { Console.WriteLine("Task {0} started", taskNumber); Console.WriteLine("Task {0} complete", taskNumber); } Task 2 started Task 2 complete Task 3 started Task 4 started Task 1 started Task 1 complete Task 3 complete Task 5 started Task 5 complete Task 4 complete Press any key to continue . . . Use the following to limit the number of concurrent tasks: ParallelOptionsparallelOptions= new ParallelOptions(); parallelOptions.MaxDegreeOfParallelism= 2;
  • 20. Threading Problems class Program { static int_counter = 0; static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } static void SubtractOne() { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } }
  • 21. Threading Problems class Program { static int_counter = 0; static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } static void SubtractOne() { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } Incremented counter to 1. Decremented counter to -1. Final counter value is -1.
  • 22. Threading Problems class Program { static int_counter = 0; static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } static void SubtractOne() { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } Incremented counter to 1. Decremented counter to -1. Final counter value is -1.
  • 23. Threading Problems class Program { static int_counter = 0; static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } static void SubtractOne() { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } Incremented counter to 1. Decremented counter to -1. Final counter value is -1. Race Conditions
  • 25. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { lock (_lock) { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } } static void SubtractOne() { lock (_lock) { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } } Race Conditions
  • 26. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { lock (_lock) { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } } static void SubtractOne() { lock (_lock) { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } } Race Conditions New
  • 27. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { lock (_lock) { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } } static void SubtractOne() { lock (_lock) { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } } Race Conditions Shared object
  • 28. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { lock (_lock) { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } } static void SubtractOne() { lock (_lock) { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } } Race Conditions Locking the shared object for each thread
  • 29. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { lock (_lock) { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } } static void SubtractOne() { lock (_lock) { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } } The right output Incremented counter to 1. Decremented counter to 0. Final counter value is 0.
  • 31. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { lock (_lock) { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } } static void SubtractOne() { lock (_lock) { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } } Not good, don’t do this, or lock a string or etc.
  • 32. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); static void Main(string[] args) { Parallel.Invoke(AddOne, SubtractOne); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { lock (_lock) { inttemp = _counter; temp++; Thread.Sleep(2000); Console.WriteLine("Incremented counter to {0}.", temp); _counter = temp; } } static void SubtractOne() { lock (_lock) { inttemp = _counter; temp--; Thread.Sleep(2000); Console.WriteLine("Decremented counter to {0}.", temp); _counter = temp; } } } The best choice for a locking object is a private or protected object defined within the class that controls the shared state.
  • 34. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); constintsleepAmount= 500; static void Main(string[] args) { Thread tAdd= new Thread(AddOne); Thread tSub= new Thread(SubtractOne); tAdd.Start(); tSub.Start(); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { Monitor.Enter(_lock); try { _counter++; Thread.Sleep(sleepAmount); Console.WriteLine("Incremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } static void SubtractOne() { Monitor.Enter(_lock); try { _counter--; Thread.Sleep(sleepAmount); Console.WriteLine("Decremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } } }
  • 35. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); constintsleepAmount= 500; static void Main(string[] args) { Thread tAdd= new Thread(AddOne); Thread tSub= new Thread(SubtractOne); tAdd.Start(); tSub.Start(); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { Monitor.Enter(_lock); try { _counter++; Thread.Sleep(sleepAmount); Console.WriteLine("Incremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } static void SubtractOne() { Monitor.Enter(_lock); try { _counter--; Thread.Sleep(sleepAmount); Console.WriteLine("Decremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } } } Monitor Lock
  • 36. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); constintsleepAmount= 500; static void Main(string[] args) { Thread tAdd= new Thread(AddOne); Thread tSub= new Thread(SubtractOne); tAdd.Start(); tSub.Start(); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { Monitor.Enter(_lock); try { _counter++; Thread.Sleep(sleepAmount); Console.WriteLine("Incremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } static void SubtractOne() { Monitor.Enter(_lock); try { _counter--; Thread.Sleep(sleepAmount); Console.WriteLine("Decremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } } } Acquire Lock
  • 37. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); constintsleepAmount= 500; static void Main(string[] args) { Thread tAdd= new Thread(AddOne); Thread tSub= new Thread(SubtractOne); tAdd.Start(); tSub.Start(); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { Monitor.Enter(_lock); try { _counter++; Thread.Sleep(sleepAmount); Console.WriteLine("Incremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } static void SubtractOne() { Monitor.Enter(_lock); try { _counter--; Thread.Sleep(sleepAmount); Console.WriteLine("Decremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } } } Release Lock
  • 38. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); constintsleepAmount= 500; static void Main(string[] args) { Thread tAdd= new Thread(AddOne); Thread tSub= new Thread(SubtractOne); tAdd.Start(); tSub.Start(); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { Monitor.Enter(_lock); try { _counter++; Thread.Sleep(sleepAmount); Console.WriteLine("Incremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } static void SubtractOne() { Monitor.Enter(_lock); try { _counter--; Thread.Sleep(sleepAmount); Console.WriteLine("Decremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } } } Final counter value is 0. Incremented counter to 1. Decremented counter to 0. Press any key to continue . . .
  • 39. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); constintsleepAmount= 500; static void Main(string[] args) { Thread tAdd= new Thread(AddOne); Thread tSub= new Thread(SubtractOne); tAdd.Start(); tSub.Start(); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { Monitor.Enter(_lock); try { _counter++; Thread.Sleep(sleepAmount); Console.WriteLine("Incremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } static void SubtractOne() { Monitor.Enter(_lock); try { _counter--; Thread.Sleep(sleepAmount); Console.WriteLine("Decremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } } } Final counter value is 0. Incremented counter to 1. Decremented counter to 0. Press any key to continue . . . Why?
  • 40. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); constintsleepAmount= 500; static void Main(string[] args) { Thread tAdd= new Thread(AddOne); Thread tSub= new Thread(SubtractOne); tAdd.Start(); tSub.Start(); tAdd.Join(); tSub.Join(); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { Monitor.Enter(_lock); try { _counter++; Thread.Sleep(sleepAmount); Console.WriteLine("Incremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } static void SubtractOne() { Monitor.Enter(_lock); try { _counter--; Thread.Sleep(sleepAmount); Console.WriteLine("Decremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } } } Blocks the calling thread until the thread terminates
  • 41. Threading Problems class Program { static int_counter = 0; static object _lock = new object(); constintsleepAmount= 500; static void Main(string[] args) { Thread tAdd= new Thread(AddOne); Thread tSub= new Thread(SubtractOne); tAdd.Start(); tSub.Start(); tAdd.Join(); tSub.Join(); Console.WriteLine("Final counter value is {0}.", _counter); } static void AddOne() { Monitor.Enter(_lock); try { _counter++; Thread.Sleep(sleepAmount); Console.WriteLine("Incremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } static void SubtractOne() { Monitor.Enter(_lock); try { _counter--; Thread.Sleep(sleepAmount); Console.WriteLine("Decremented counter to {0}.", _counter); } finally { Monitor.Exit(_lock); } } } } Incremented counter to 1. Decremented counter to 0. Final counter value is 0. Press any key to continue . . . Blocks the calling thread until the thread terminates
  • 42. Task.Factory varmyTask= Task.Factory.StartNew(() => { return "Hello, world!"; }); Console.WriteLine(myTask.Result);
  • 44. Wait int[] values = null; Task loadDataTask= new Task(() => { Console.WriteLine("Loading data..."); Thread.Sleep(5000); values = Enumerable.Range(1,10).ToArray(); }); loadDataTask.Start(); Console.WriteLine("Data total = {0}", values.Sum());
  • 45. Wait int[] values = null; Task loadDataTask= new Task(() => { Console.WriteLine("Loading data..."); Thread.Sleep(5000); values = Enumerable.Range(1,10).ToArray(); }); loadDataTask.Start(); Console.WriteLine("Data total = {0}", values.Sum()); Will throw ArgumentNullExceptionbecause we are trying to use the array before it has been populated by the parallel task.
  • 46. Wait int[] values = null; Task loadDataTask= new Task(() => { Console.WriteLine("Loading data..."); Thread.Sleep(5000); values = Enumerable.Range(1,10).ToArray(); }); loadDataTask.Start(); Console.WriteLine("Data total = {0}", values.Sum()); Will throw ArgumentNullExceptionbecause we are trying to use the array before it has been populated by the parallel task. int[] values = null; Task loadDataTask= new Task(() => { Console.WriteLine("Loading data..."); Thread.Sleep(5000); values = Enumerable.Range(1,10).ToArray(); }); loadDataTask.Start(); loadDataTask.Wait(); loadDataTask.Dispose(); Console.WriteLine("Data total = {0}", values.Sum()); // Data total = 55
  • 47. int[] values = null; Task loadDataTask= new Task(() => { Console.WriteLine("Loading data..."); Thread.Sleep(5000); values = Enumerable.Range(1,10).ToArray(); }); loadDataTask.Start(); loadDataTask.Wait(); loadDataTask.Dispose(); Console.WriteLine("Data total = {0}", values.Sum()); // Data total = 55 Wait int[] values = null; Task loadDataTask= new Task(() => { Console.WriteLine("Loading data..."); Thread.Sleep(5000); values = Enumerable.Range(1,10).ToArray(); }); loadDataTask.Start(); Console.WriteLine("Data total = {0}", values.Sum()); To fix it, we will now waitfor the task to be done
  • 48. int[] values = null; Task loadDataTask= new Task(() => { Console.WriteLine("Loading data..."); Thread.Sleep(5000); values = Enumerable.Range(1,10).ToArray(); }); loadDataTask.Start(); loadDataTask.Wait(); loadDataTask.Dispose(); Console.WriteLine("Data total = {0}", values.Sum()); Wait int[] values = null; Task loadDataTask= new Task(() => { Console.WriteLine("Loading data..."); Thread.Sleep(5000); values = Enumerable.Range(1,10).ToArray(); }); loadDataTask.Start(); Console.WriteLine("Data total = {0}", values.Sum()); The output will be Data total = 55
  • 49. Tasks Continuation Task continuation = firstTask.ContinueWith(antecedent => { /* functionality */ });