I'm running in a loop and kicking off tasks in the following manner:
var iResult = new List<Task>();
foreach(var i in myCollection)
{
var task = Task.Factory.StartNew(() =>
DoSomething(), TaskCreationOptions.LongRunning);
task.ContinueWith(m => myResponseHandler(m.Result));
iResult.Add(task);
}
Within my DoSomething()
method, I have a timer:
public static myMsg DoSomething()
{
var timer = System.Diagnostics.Stopwatch.StartNew();
DoLongRunningTask(); //If it matters this hits a REST endpoint (https)
timer.Stop();
return new myMsg(timer.ElaspedMilliseconds);
}
When I iterate through my list of myMsg
's the ElaspedMilliseconds seems to be completely additive - the ElaspedMilliseconds on the first one might be 300, but the last one could be 50000 (50 seconds) - which is actually the approximate time the entire thing takes to run (as measured by another timer).
Edit:
Ooops, I was also first confused.
The problem is that it only looks aditive (accumulative) because the ElapsedTime values are always output in increasing order only.
So, if I have, as in my demo below, in the order of launching:
then the results appear in output out of initial order - ALWAYS in order of increasing duration of tasks:
Here is the output from Console app below:
And it is obvious why - because the faster task always finishes and output before longer (more time consuming) task.
One thing that is most likely to happen is that
DoLongRunningTask()
might not be multithreaded properly, which mean one task run after the first is completed and so on. Each task has its own timer and they are all start somewhere around the same time (or as threads are allocated to the tasks), but the long running task offset them all.You never have an unlimited thread pool and Tasks handles who get a thread and when.
About LongRunning:
"It's not a specific length per se. If you're generating a lot of tasks, LongRunning is not appropriate for them. If you're generating one or two tasks that will persist for quite some time relative to the lifetime of your application, then LongRunning is something to consider. In general, don't use it unless you find that you really need it. Under the covers, it's going to result in a higher number of threads being used, because its purpose is to allow the ThreadPool to continue to process work items even though one task is running for an extended period of time; if that task were running in a thread from the pool, that thread wouldn't be able to service other tasks. You'd typically only use LongRunning if you found through performance testing that not using it was causing long delays in the processing of other work." - Stephen Toub