Do I have to lock access to instance members?
Example:
public class HttpModule : IHttpModule
{
//...
Dictionary<int, int> foo;
void UseFoo(int a, int b)
{
foo[a] = b;
}
}
Do I have to lock access to instance members?
Example:
public class HttpModule : IHttpModule
{
//...
Dictionary<int, int> foo;
void UseFoo(int a, int b)
{
foo[a] = b;
}
}
It's not crystal clear to me so far from the MSDN documentation, but I found a forum post from someone who claims to know the answer. It sounds like you shouldn't expect bad stuff to happen with your implementation, but you should be aware that foo
's state will not necessarily be shared across all results since your HttpModule
will be created once per HttpApplication
that IIS chooses to keep in its pool.
I wanted to offer here my findings related to this question as I have observed in IIS6:
I have been dealing with this issue extensively in IIS6 and have found some interesting results utilizing log4net and reflection to capture execution history. What I have found is that there is extensive 'thread management' going on behind the scenes. It seems that there is a 'primary' series of threads that corresponds 1:1 to HttpApplication
. These threads however to do not exclusively handle the pipeline for your request. Various different sub-threads can be called when these instances are accessed. Subsequent new requests and resource requests utilized by your application seem to share some persistent information relating to your original request but are yet never handled entirely by the initial thread indicating some type of relationship. I could not discern any concrete pattern (other than what i've previously described) as to which elements were divvied to other threads as it was seemingly random. My conclusion to this evidence is that there is some concept of hierarchical pooling? occurring where some unknown subset of reference elements are inherited in the child threads through the parent reference.
So as an answer I would say that HttpModules
are shared between threads. In terms of locking instance values, this would be applicable if the values apply to all requests which use the module and must maintain some state. I could see this being useful if attempting to maintain stateful instance values which are expensive to ascertain so that they could be reused in subsequent requests.
This issue had been troubling me for some time hopefully this info helps someone.
I recently found an article which touches on this question slightly: http://www.dominicpettifer.co.uk/Blog/41/ihttpmodule-gotchas---the-init---method-can-get-called-multiple-times
It doesn't mention threads, but only says that the worker process will
instantiate as many HttpApplication objects as it thinks it needs, then it'll pool them for performance reasons, reusing instances as new requests come in before sending them back into the pool.
Following the code in from the link, you can be sure that your init code is executed once in a thread-safe manner:
private static bool HasAppStarted = false;
private readonly static object _syncObject = new object();
public void Init(HttpApplication context)
{
if (!HasAppStarted)
{
lock (_syncObject)
{
if (!HasAppStarted)
{
// Run application StartUp code here
HasAppStarted = true;
}
}
}
}
I've been meaning to set up a test app to run this and test it, just to see if it's true, but I haven't had the time.
The article posted by Jim is interesting, but as Jim says it does not mention anything about thread safety.
I guess you would only need the lock mechanism if you are initializing static members or performing "only once" initializations i.e. initializing a static resource.
I couldn't conclude from MSDN nor the article mentioned by Jim that we need the lock mechanism when initializing non-static class variables.
© 2022 - 2024 — McMap. All rights reserved.