2

I am calling from one piece of my code through several layers of 3rd party code, and the call surfaces back into my code at some point by calling some code I've written.

In other words, the code call chain looks like this:

My code #1 --> 3rd party code --> My code #2

Unfortunately, nothing I pass to the 3rd party code is given to that second piece of code so I have nothing to tie the first piece and the second piece together, except for the fact that the code runs on the same thread.

So I was wondering if simply using [ThreadStatic] on a static field on a class would be a viable solution to this?

Since the code also runs in a web application, I cannot just use a static field for this, since the value I need access to (an object) is different for each user/session.

ie. I would do something like this:

internal static class DataHolder
{
    [ThreadStatic]
    internal static ClassName FieldName;
}

Are there other solutions to this?

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • You'd have to hand the 3rd party code some kind of delegate to get called back. That ought to give you a way to hang an object off of it. – Hans Passant Mar 22 '11 at 16:54
  • unfortunately it's not that simple, the only place to attach an event is through a static event (don't hang me, I didn't design that piece of sh**), and so there is just one common surface point out from the 3rd party library. – Lasse V. Karlsen Mar 22 '11 at 16:59
  • It doesn't matter that the event is static, the delegate instance you create matters. Compare to SystemEvents. – Hans Passant Mar 22 '11 at 17:11

4 Answers4

3

In contrast to the other answers suggesting that this is ok, you should be very careful about using ThreadStatic or ThreadLocal<T> in an ASP.NET application.

ASP.NET utilises thread-agility, meaning that the same request can potentially be handled by several threads. To be safe you'd need to break encapsulation and store your items in the current HttpContext, rather than using ThreadStatic or ThreadLocal<T>:

internal static class DataHolder
{
    internal static ClassName PropertyName
    {
        get { return (ClassName)System.Web.HttpContext.Current.Items["foo"]; }
        set { System.Web.HttpContext.Current.Items["foo"] = value; }
    }
}

Unfortunately this thread-agility "feature" is very poorly documented. I'm reasonably sure that the thread switch can only happen at certain points in the lifecycle, not arbitrarily, so depending on exactly how and where in the lifecycle the code is used you might be safe with ThreadStatic or ThreadLocal<T>.

I'll try to dig out some links...

LukeH
  • 263,068
  • 57
  • 365
  • 409
  • Do you happen to know where those points are? In this case the call chain is basically that I call into the third party code, and that code calls my code through a static event, which means that it is the same instance (if any) that ends up getting the target call. There's no ASP.NET code being touched as part of this as the 3rd party code have no ties to ASP.NET. – Lasse V. Karlsen Mar 22 '11 at 17:06
  • Though it might mean that I have to layer off this part of the code so that in non-ASP.NET I use ThreadStatic or ThreadLocal, and in ASP.NET I need to use HttpContext.Current, without the involved code actually caring either way. – Lasse V. Karlsen Mar 22 '11 at 17:06
  • @Lasse: There's lots of anecdotal evidence around -- just plug "thread agility asp.net" into Google -- but I've struggled in the past, without success, to find any definitive documentation. There's a good treatment of it in http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html. – LukeH Mar 22 '11 at 17:11
  • Ok, sounds like I need to investigate this more... or, perhaps that time for the rewrite/replacement of this has finally come around. – Lasse V. Karlsen Mar 22 '11 at 17:18
2

ThreadLocal<T> for .NET 4 as mentioned in this question:

are static classes shared among different threads in C#

However, having been in that boat myself - I ended up going down the static route. It worked and was safe because it was manageable state.

Community
  • 1
  • 1
Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
2

Yes. ThreadStatic will work for that. You might want to look into ThreadLocal, which simplifies working with thread static variables.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
2

Yes, [ThreadStatic] should work in the scenario you describe if you can be absolutely certain that the 3rd party code always calls you back on the same thread that you called into the 3rd party code on. In many async callback models, this is often not guaranteed. If the callback is strictly defined as a synchronous callback, then you're probably ok.

dthorpe
  • 35,318
  • 5
  • 75
  • 119
  • It does, I've verified through reflector, so that's not a problem. – Lasse V. Karlsen Mar 22 '11 at 16:59
  • Just because the 3rd party code calls you back on the same thread now doesn't mean it always will. The implementation could change in a future revision of the 3rd party code, or your test case might not be hitting it hard enough to cause it to "spill" into other worker threads. If the 3rd party documentation states that the callback will be called on the same thread, then confidence is higher. Empirical observation is dicey for making architectural decisions of this scale. – dthorpe Mar 22 '11 at 17:09
  • Case in point: LukeH's note about ASP.NET "thread agility" is exactly the sort of thing that would throw a wrench in the works for using thread-local storage. – dthorpe Mar 22 '11 at 17:11
  • The third party library, in this project, has exactly one upgrade path, and that is to be rewritten or replaced. The static event there is not the only problem with it, but unfortunately it does what it does well enough that I was able to deliver the project on time, even though there are some unwanted bits in there, but right now it's starting to become more painful than a rewrite/replacement might be, so this is just a short-time patch anyway. – Lasse V. Karlsen Mar 22 '11 at 17:17