c# - How do Tasks in the Task Parallel Library affect ActivityID? -
before using task parallel library, have used correlationmanager.activityid keep track of tracing/error reporting multiple threads.
activityid stored in thread local storage, each thread get's own copy. idea when fire thread (activity), assign new activityid. activityid written logs other trace information, making possible single out trace information single 'activity'. useful wcf activityid can carried on service component.
here example of i'm talking about:
static void main(string[] args) { threadpool.queueuserworkitem(new waitcallback((o) => { dowork(); })); } static void dowork() { try { trace.correlationmanager.activityid = guid.newguid(); //the functions below contain tracing logs activityid. callfunction1(); callfunction2(); callfunction3(); } catch (exception ex) { trace.write(trace.correlationmanager.activityid + " " + ex.tostring()); } } now, tpl, understanding multiple tasks share threads. mean activityid prone being reinitialized mid-task (by task)? there new mechanism deal activity tracing?
i ran experiments , turns out assumption in question incorrect - multiple tasks created tpl not run on same thread @ same time.
threadlocalstorage safe use tpl in .net 4.0, since thread can used 1 task @ time.
the assumption tasks can share threads concurrently based on interview heard c# 5.0 on dotnetrocks (sorry, can't remember show was) - question may (or may not) become relevant soon.
my experiment starts number of tasks, , records how many tasks ran, how long took, , how many threads consumed. code below if repeat it.
class program { static void main(string[] args) { int totalthreads = 100; taskcreationoptions taskcreationopt = taskcreationoptions.none; task task = null; stopwatch stopwatch = new stopwatch(); stopwatch.start(); task[] alltasks = new task[totalthreads]; (int = 0; < totalthreads; i++) { task = task.factory.startnew(() => { dolongrunningwork(); }, taskcreationopt); alltasks[i] = task; } task.waitall(alltasks); stopwatch.stop(); console.writeline(string.format("completed {0} tasks in {1} milliseconds", totalthreads, stopwatch.elapsedmilliseconds)); console.writeline(string.format("used {0} threads", threadids.count)); console.readkey(); } private static list<int> threadids = new list<int>(); private static object locker = new object(); private static void dolongrunningwork() { lock (locker) { //keep record of managed thread used. if (!threadids.contains(thread.currentthread.managedthreadid)) threadids.add(thread.currentthread.managedthreadid); } guid g1 = guid.newguid(); trace.correlationmanager.activityid = g1; thread.sleep(3000); guid g2 = trace.correlationmanager.activityid; debug.assert(g1.equals(g2)); } } the output (of course depend on machine) was:
completed 100 tasks in 23097 milliseconds used 23 threads changing taskcreationopt taskcreationoptions.longrunning gave different results:
completed 100 tasks in 3458 milliseconds used 100 threads
Comments
Post a Comment