tasks that can be done in parallel
static void Main(string[] args)
{
Parallel.For(1, 10, i => DoWork(i));
Thread.Sleep(12000);
}
static void DoWork(int i)
{
Thread.Sleep(1000);
Console.WriteLine(i);
}
}
// or we can use parallel options to adjust threads
ParallelOptions options = new ParallelOptions();
options.CancellationToken = new CancellationTokenSource().Token;
options.MaxDegreeOfParallelism = -1; // default
options.TaskScheduler = TaskScheduler.Default; // default
Parallel.For(1, 3, options, DoWork(i));
output
1
2
4
3
5
6
7
8
9
Or the same with parallel
Parallel.ForEach(collection, item => DoWork(item));
Or the same with invoke
static void Main(string[] args)
{
Parallel.Invoke(() => Console.WriteLine("Invoke 1"),
() => Console.WriteLine("Invoke 2"),
() => Console.WriteLine("Invoke 3")
);
Thread.Sleep(12000);
}
output
Invoke 2
Invoke 3
Invoke 1
PARALLEL WITH INIT BODY FINISH LAMDAS
int[] nums = Enumerable.Range(1, 3).ToArray();
long total = 0;
Parallel.ForEach<int, long>(
nums,
() => 0,
(j, loop, subtotal) =>
{
subtotal += j;
return subtotal;
},
(finalResult) => Interlocked.Add(ref total, finalResult)
);
Thread.Sleep(2000);
Console.WriteLine("Result is {0:N0}", total);
One good example from stackOverflow
public void MyParallelizedMethod()
{
// Shared variable. Not thread safe
var itemCount = 0;
Parallel.For(myEnumerable,
// localInit - called once per Task.
() =>
{
// Local `task` variables have no contention
// since each Task can never run by multiple threads concurrently
var sqlConnection = new SqlConnection("connstring...");
sqlConnection.Open();
// This is the `task local` state we wish to carry for the duration of the task
return new
{
Conn = sqlConnection,
RunningTotal = 0
}
},
// Task Body. Invoked once per item in the batch assigned to this task
(item, loopState, taskLocals) =>
{
// ... Do some fancy Sql work here on our task's independent connection
using(var command = taskLocals.Conn.CreateCommand())
using(var reader = command.ExecuteReader(...))
{
if (reader.Read())
{
// No contention for `taskLocal`
taskLocals.RunningTotal += Convert.ToInt32(reader["countOfItems"]);
}
}
// The same type of our `taskLocal` param must be returned from the body
return taskLocals;
},
// LocalFinally called once per Task after body completes
// Also takes the taskLocal
(taskLocals) =>
{
// Any cleanup work on our Task Locals (as you would do in a `finally` scope)
if (taskLocals.Conn != null)
taskLocals.Conn.Dispose();
// Do any reduce / aggregate / synchronisation work.
// NB : There is contention here!
Interlocked.Add(ref itemCount, taskLocals.RunningTotal);
}