cannot understand an example in a book from apress talking about a misused case of threadlocal with task construct in TPL.
Why isn't it become 10000 in number as expected results?
Could anyone give a more detailed explanation on the program flow of below program for which line execute instantly and some lines async in time? the sequence and order of execution?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Listing_05 {
class BankAccount {
public int Balance {
get;
set;
}
}
class Listing_05 {
static void Main(string[] args) {
// create the bank account instance
BankAccount account = new BankAccount();
// create an array of tasks
Task<int>[] tasks = new Task<int>[10];
// create the thread local storage
ThreadLocal<int> tls = new ThreadLocal<int>(() => {
Console.WriteLine("Value factory called for value: {0}",
account.Balance);
return account.Balance;
});
for (int i = 0; i < 10; i++) {
// create a new task
tasks[i] = new Task<int>(() => {
// enter a loop for 1000 balance updates
for (int j = 0; j < 1000; j++) {
// update the TLS balance
tls.Value++;
}
// return the updated balance
return tls.Value;
});
// start the new task
tasks[i].Start();
}
// get the result from each task and add it to
// the balance
for (int i = 0; i < 10; i++) {
//added by myself to see any hints but still cannot have insights
Console.WriteLine("task {0} results {1}", i, tasks[i].Result);
//end of my editing
account.Balance += tasks[i].Result;
}
// write out the counter value
Console.WriteLine("Expected value {0}, Balance: {1}",
10000, account.Balance);
// wait for input before exiting
Console.WriteLine("Press enter to finish");
Console.ReadLine();
}
}
}
Results in a computer using 8 cores i7 cpu, shall be 8 threads. Run Several times and below are 2 out of many executions.


Do not understand how the programs work and behave in this way
Tasks provide a mechanism to run code concurrently. This does not mean they will necessarily run on separate threads or even if multiple threads are used that they will not be reused.
Do not try to use thread local storage with Tasks at all.
Alternative storage options are to use a closure within the tasks's lambda function, or create a class and put data on that class and use a method of that class as the Task's callee. I personally feel this is a lot cleaner anyways.
Hans Passant also mentioned AsyncLocal in comments which would be worth researching (I haven't used it myself so can't comment).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With