2. Overview of the First Project
Objective: unattended process for a customer
offering PoS backup service to their clients.
Multithreading Challenge: with number of
options available in .Net - which one suits my
needs with minimal implementation effort and
flexible enough settings?
Decision: combination of Parallel.Invoke to
controll max number of threads and
IAsyncResult to control thread timeout.
5. Options for Parallelism in .Net
The best article I came across from Microsoft
Thread - tried and true, but feels antiquated.
Task and Action - seems to be great option for
iterative processing where a loop-cycle can check
for cancellation token.
Task.Factory and Parallel - powerful for spreading
the load between threads and with somewhat
overwhelming options.
PLINQ - great simplicity, not so much for control
over number of threads and/or for thread timeout.
IAsyncResult - elegant timeout support.
6. Control Number of Threads
The most elegant approach I found to control
number of threads:
System.Threading.Tasks.Parallel.Invoke
(
new System.Threading.Tasks.ParallelOptions()
{
//Config settings for the application
MaxDegreeOfParallelism = configuration.MaxThreads,
},
processFileActions.ToArray() //List<Action>
);
Adopted from:
http://stackoverflow.com/questions/2898609/system-threading-tasks-limit-the-
number-of-concurrent-tasks
7. Control Thread Timeout (void)
The most elegant approach I found to control
thread timeout (without aborting thread):
Thread threadToKill = null;
Action wrappedAction = () => {
threadToKill = Thread.CurrentThread;
action();};
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds)) {
wrappedAction.EndInvoke(result);}
else { threadToKill.Abort();
throw new TimeoutException();}
Adopted from:
http://stackoverflow.com/questions/299198/implement-c-sharp-generic-timeout
8. Control Thread Timeout (<T>)
In case thread needs to return data back to
caller:
Task<T> task = Task.Factory.StartNew<T>(operation);
task.Wait(timeoutMilliseconds);
if (!task.IsCompleted)
{
throw new TimeoutException();
}
else
{
return task.Result;
}
9. A concurrency hiccup..
I am using NLog for tracing and some log entry
never got recorded
Assuming concurrency is the issue - how to
solve?
Lock { } is a sure bottleneck. System.Thread.
Monitor seems to work great:
private static System.Lazy<object> syncRoot =
new Lazy<object>(() => { return new object(); });
if (System.Threading.Monitor.TryEnter(syncRoot, 100))
Logger._nLogger.Value.Log(level, message);
Adopted from:
http://stackoverflow.com/questions/5565395/better-solution-to-multithreading-riddle
10. Overview of the Second Project
Objective: unattended process for Bell.ca web
site to purge unused online profiles.
Multithreading Challenge: with tens of
millions of records of raw data - where to use
multithreading and where not to, how to avoid
killing the Sql Server database, the Smtp, or
the sFtp?
Decision: combination of PLinq.ForAll() and
process time-to-live.
11. Control Number of Threads
The easiest approach I found to control number
of threads with PLinq:
candidates
.AsParallel()
.WithDegreeOfParallelism(10)
.ForAll(c =>ProcessCandidate(c));
Where candidates is list of EntityFramework
objects and ProcessCandidate is a method to
send an email to each customer.
12. What to/what not to Multithread?
Do:
● sFtp file download and upload as slow but
not taxing process on local machine
resources
● File decompress and compress as multi-core
CPU's are readily available.
● Massive data inserts into Sql Server using
BCP Utility as database is on another
machine and LAN is fast.
Do not:
● Email Notification - to avoid race condition