Using a ThreadStatic Field with a Job

START EDIT

The “right” way to do this (pre-4.5) is to use the SynchronizationContext, as described here: http://msdn.microsoft.com/en-us/magazine/gg598924.aspx

I believe that in version 4.5, the SynchronizationContext is automatically processed for you using the async / await keywords, but it did not confirm sufficient work.

In 4.0, you can use "TaskScheduler.FromCurrentSynchronizationContext" to capture the current context of the stream (in my case, this will include HttpContext, but different parts of BCL provide similar constructs).

End edit

The main question:

Is the next "secure" mechanism for sharing "context" with the task?

Without going into details, in my case, it is impossible to go directly to the context.

public static class ContextCaller{ [ThreadStatic] public static object SharedState; public static Task InvokeWithContext(this Action theAction){ //We're still running in the "outer" context, //so we can collect a variable and store it in the thread-static //field by closing it into the task. var context = new object(); var t = new Task(()=>{ try{ //close in the context SharedState = context; theAction(); } finally{ //teardown the shared state. SharedState = null; } }); t.Start(); return t; } } 

And now the client code:

 //client code: Action doWork = ()=>{ var state = ContextCaller.SharedState; //do work on state, potentially throwing an exception in the process. }; //cause the task to be invoked with some data available only on this thread. doWork.InvokeWithContext(); 

Based on my understanding of the relationship between the task and the thread, the above should be safe because:

  • One task will be executed exactly in one thread (provided that the action does not generate additional tasks / threads).
  • The ThreadStatic field is set before executing "theAction ()" and "finally" ensures that this field is reset after calling "theAction ()", regardless of the result.

Besides explicitly closing the "theAction" parameters, are there other, better templates for determining the context in the task?

+4
source share
1 answer

I see no technical reasons why your code should not work fine.

But I also think that this is bad practice, and I will use something like that only if there is no other way. And I think that adding another overload of your method that accepts an Action<object> (or even better using a strongly typed parameter) should not be a significant change.

+1
source

All Articles