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.
Related
I'm developing an app with VS2013, using EF6.02, and Web API 2. I'm using the ASP.NET SPA template, and creating a RESTful api against an entity framework data source backed by a sql server. (In development, this resides on the SQL Server local instance.)
I've got two API methods so far (one that just reads data, one that writes data), and I'm testing them by calling them in the javascript. When I only call a single method in my script, either one works perfectly. But if I call both in script (without waiting for either's callback to fire), I get bad results and different exceptions in the debugger. Some exceptions state that the save can't be completed because there are pending transactions. Another exception stated something about a conflict with other threads. And sometimes, the read operation fails with a null pointer exception when trying to read a result set.
"New transaction is not allowed because there are other threads running in the session."
This makes me question if I'm correctly getting a new DBContext per request. My code for this looks like:
static Startup()
{
context = new Data.SqlServer.AppDbContext();
...
}
and then whenever instantiating a unit of work, I access Startup.context.
I've tried to implement the unit of work pattern, and each request shares a single UOW object which has a single DBContext object.
My question: Do I have additional responsibility to ensure that web requests "play nicely" with eachother? I hope that this is a problem that others have already dealt with. Perhaps the errors that I'm seeing are legitimate in the sense that if one user's data is being touched, it is temporarily in an invalid state and if other requests come in at that exact moment, they indeed will fail (and I should code anticipating these failures). I guess that even if each request has its own DBContext, they still share the same underlying SQL data source so perhaps that's causing issues.
I can try to put together a testcase, but I get differing behavior depending on where I put breakpoints and how long I spend on them, reaffirming to me that this is timing related.
Thanks for any help or suggestions...
-Ben
Your problem is where you are setting your context. The Startup method is for when the entire application starts, thus any request made will all use the same context. This is not a per request setup, but rather a per application setup. As to why you are getting the errors, EntityFramework is NOT thread-safe. Since IIS spawns many threads to handle concurrent request, your single context is being used across multiple threads.
As for a solution, you can look into
-Dependency Injection frameworks (such as Ninject or Unity)
-place a using statement in your UnitOfWork classes
using(var context = new Data.SqlServer.AppDbContext()){//do stuff}
-Or, I have seen instances of people creating a class that gets the context for that request and stores it in the HttpContext.Cache[] element (using a unique name so you can retrieve it in another class easily), making it so that you will reuse the same context for the same request. Something like this:
public AppDbContext GetDbContext()
{
var httpContext = HttpContext.Current;
if (httpContext == null) return new AppDbContext();
const string contextTypeKey = "AppDbContext";
if (httpContext.Items[contextTypeKey] == null)
{
httpContext.Items.Add(contextTypeKey, new AppDbContext());
}
return httpContext.Items[contextTypeKey] as AppDbContext;
}
To use the above method, make a simple call var context = GetDbContext();
Note
We have all of the above methods, but this is specifically to the third method. It seems to work well with two caveats. First, do not use this in a using statement as it will not be available to any other classes during the scope of the request (you dispose it). And secondly, ensure that you have a call on Application_EndRequest that does actually dispose of it. We saw these little buggers hanging around after the request ended in memory causing a huge spike in memory usage.
The context:
(Note: in the following I am using "project" to refer to a collection of software deliverables, intended for a single customer or a specific market. I am not referring to "project" as it is used in Visual Studio to refer to a configuration that builds a single EXE or DLL, within a solution.)
We have a sizable system that consists of three layers:
A layer containing code that is shared across projects
A layer containing code that is shared across different applications within a project
A layer containing code that is specific to a particular application or website within a project.
The first two layers are built into DLL assemblies. The top layer is an assortment of EXEs and/or .aspx web applications.
IIRC, we have a number of different projects that use this pattern. All four share layer 1 (though often in slightly different versions, as managed by the VCS). Each of them has its own layer 2. Each of them has its own set of deliverables, which can range from a website, or a website and a background service, to our largest and most complex (and the bread-and-butter of our business) which consists of something like five independent web applications, 20+ console applications/background services, three or four independent web services, half-a-dozen desktop GUI apps, etc.
It's been our intent to push as much code into levels 1 and 2 as possible, to avoid duplicating logic in the top layers. We've pretty much accomplished that.
Each of layers 1 and 2 produce three deliverables, a DLL containing the code that is not web-related, a DLL containing the code that is web-related, and a DLL containing unit tests.
The problem:
The lower levels were written to make extensive use of singletons.
The non-web DLL in layer 1 contains classes to handle INI files, logging, a custom-built obect-relational mapper, which handles database connections, etc. All of these used singletons.
And when we started building things on the web, all of those singletons became a problem. Different users would hit the website, log in, and start doing different things. They'd do something that generated a query, which would result in a call into the singleton ORM to get a new database connection, which would access the singleton configuration object to get the connection string, and then the connection would be asked to perform a query. And in the query the connection would access the singleton logger to log the SQL statement that was generated, and the logger would access the singleton configuration object to get the current username, so as to include it in the log, and if someone else had logged in in the meantime that singleton configuration object would have a different current user. It was a mess.
So what what we did, when we started writing web applications using this code base was to create a singleton factory class, that was itself a singleton. Every one of the other singletons had a public static instance() method that had been calling a private constructor. Instead, the public static instance() method obtained a reference to the singleton factory object, then called a method on that to get a reference to the single instance of the class in question.
In other words, instead of having a dozen classes that each maintained its own private static reference, we now had a single class that maintained a single static reference, and the object that it maintained a reference to contained a dozen references to the other, formerly singleton classes.
Now we had only one singleton to deal with. And in its public static instance() method, we added some web-specific logic. If we had an HTTPContext and that context had an instance of the factory in its session, we'd return the instance from the session. If we had an HTTPContext, and it didn't have a factory in its session, we'd construct a new factory and store it in the session, and then return it. If we had no HTTPContext, we'd just construct a new factory and return it.
The code for this was placed in classes we derived from Page, WebControl, and MasterPage, and then we used our classes in our higher-level code.
This worked fine, for .aspx web applications, where users logged in and maintained session. It worked fine for .asmx web services running within those web applications. But it has real limits.
In particular, it won't work in situations where there is no session. We're feeling pressure to provide websites that serve a larger user base - that might have tens or hundreds of thousands of users hitting them dynamically. Up to now our users have been pretty typical desktop business users. They log into our websites, and stay in them much of the day, using our web apps as an alternative to a desktop app. A given customer might have as many as six users who might use our websites, and while we have a thousand or more customers, combined they don't make for all that heavy a load. But our current architecture will not scale to that.
We're also running into situations where ASP.NET MVC would be a better fit for building the web UI than .aspx web forms. And we're exploring building mobile apps that would be communicating with stand-alone WFC web services. And while in both of these, it looks like it's possible to run them in an environment that has a session, it looks to limit their flexibility and performance fairly severely.
So, we're really looking at ways to eliminate these singletons.
What I'd really like:
I'm trying to envision a series of refactors, that would eventually lead to a better-structured, more flexible architecture. I could easily see the advantages of an IoC framework, in our situation.
But here's the thing - from what I've seen of IoC frameworks, they need their dependencies provided to them externally via constructor parameters. My logger class, for example, needs an instance of my config class, from which to obtain the current user. Currently, it is using the public static instance() method on the config class to obtain it. To use an IoC framework, I'd need to pass it as a constructor.
In other words, from where I sit, the first, and unavoidable task, is to change every class that uses any of these singletons so as to take the singleton factory as a constructor parameter. And that's a huge amount of work.
As an example, I just spent the afternoon doing exactly that, in the level 1 libraries, to see just how much work it is. I ended up changing over 1300 lines of code. The level 2 libraries will be worse.
So, are there any alternatives?
Typically, you should try to wrap the contextual information into its own instance and provide a static accessor method to refer to it. For example, consider HttpContext and its available every where in web application via HttpContext.Current.
You should try to devise something similar so that instead of returning singleton instance, you would return the instance from the current context. That way, you need to not change your consumer code that refers to these static methods (e.g. Logger.Instance()).
I generally roll-up information such as logger, current user, configuration, security permissions into application context (can be more than one class if need arises). The AppContext.Current static method returns the current context. The method implementation goes something like
public interface IContextStorage
{
// Gets the stored context
AppContext Get();
// Stores the context, context can be null
void Set(AppContext context);
}
public class AppContext
{
private static IContextStorage _storageProvider, _defaultStorageProvider;
public static AppContext Current
{
get
{
var value = _storageProvider.Get();
// If context is not available in storage then lookup
// using default provider for worker (threadpool) therads.
if (null == value && _storageProvider != _defaultStorageProvider
&& Thread.CurrentThread.IsThreadPoolThread)
{
value = _defaultStorageProvider.Get();
}
return value;
}
}
...
}
IContextStorage implementations are application specific. The static variables _storageProvider gets injected at the application start-up time while _defaultStorageProvider is a simple implementation that looks into current call context.
App Context creation happens in multiple stages - for example, a global information such as configuration gets read and cached at application start-up while specific information such as user & security gets formed at authentication stage. Once all info is available, the actual instance is created and stored into the app specific storage location. For example, desktop application will use a singleton instance while web application can probably store the instance into the session state. For web application, you may have logic at start of each request to ensure that the context is initialized.
For a scalable web applications, you can have a storage provider that will store the context instance into the cache and if not present in the cache then re-built it.
I'd recommend starting by implementing "Poor Man's DI" pattern. This is where you define two constructors in your classes, one that accepts an instance of the dependencies (IoC), and another default constructor that new's them up (or calls a singleton).
This way you can introduce IoC incrementally, and still have everything else work using the default constructors. Eventually when you have IoC being used in most places you can start to remove the default constructors (and the singletons).
public class Foo {
public Foo(ILogger log, IConfig config) {
_logger = log;
_config = config;
}
public Foo() : this(Logger.Instance(), Config.Instance()) {}
}
We have a web front end on our business layer server.
Certain pages in our web application instantiate very long running tasks (could be up to 10+ minutes). The way that these requests are handled is like so: -
(on the HTTP request thread)
we make a connection to the business server.
we create a new thread to make the long running call passing in the connection object.
The HTTP request then completes, passing a handle back to the browser,
the browser periodically polls the web server to get updates on the long running task progress.
All requests to the business server are authenticated - the connection's user principal page must have permission to call the method on the business server.
This mechanism works fine as long as our web application is running in Classic mode.
When we run in pipeline mode, we get ObjectDisposedExceptions when the browser polls.
System.ObjectDisposedException: Safe handle has been closed
at System.StubHelpers.StubHelpers.SafeHandleC2NHelper(Object pThis, IntPtr CleanupWorkList)
at Microsoft.Win32.Win32Native.GetTokenInformation(SafeTokenHandle TokenHandle, UInt32 TokenInformationClass, SafeLocalAllocHandle TokenInformation, UInt32 TokenInformationLength, ref UInt32 ReturnLength)
at System.Security.Principal.WindowsIdentity.GetTokenInformation(SafeTokenHandle tokenHandle, TokenInformationClass tokenInformationClass, ref UInt32 dwLength)
at System.Security.Principal.WindowsIdentity.get_User()
at System.Security.Principal.WindowsIdentity.GetName()
at System.Security.Principal.WindowsIdentity.get_Name()
the problem appears to be that the windows principal used to make the connection is disposed when the original request ends (which is understandable - in fact I am surprised that the code worked at all!).
As a way around this problem I was wondering if it was possible to either create a duplicate of the HTTP request principal and use that to create the connection (and dispose of it when the long running task completes) or would it be possible to impersonate the HTTP request principle on the worker thread even after the principal is disposed?
Update
(My comment under Aliostad's question was incorrect: the test page did fail. I managed to confuse myself sufficiently that I wrote my test page so that it did not exercise the same code path as the real (faulting) code. Nevermind!)
I have written a "workaround" for this problem: -
I am in the fortunate position of knowing what roles/groups the business server logic will be querying for before the call to the business server is made. So my workaround is to create a new generic principal based upon the request's principal's membership of these roles. The long running task is run using the generic principal.
I am not 100% happy with this workaround because it is very much a "hack" - i.e. I can see that it would easily fall down if some logic did the (eminently sensible) check of verifying that the principal's identity is authenticated.
So I would still very much appreciate any help / insight into this issue.
Thanks
OK, here is my catch on this.
First of all, if you create a thread, all the current thread's security context will be copied to the new thread - by default. This operation is heavy but much needed (as you can imagine most things will not work without it). In case you need to prevent it and you do not need the copying of context, there is a way to do it and it has been explained in Richter's C# via CLR. Lucky enough, he has shared this very bit of the book here and basically calling a static method to prevent context to be flowed:
ExecutionContext.SuppressFlow();
I cannot think this is being called in WCF although using Reflector, I found a single use of it in here:
[SecuritySafeCritical]
private IAsyncResult BeginGetContext(bool startListening)
{
Exception exception;
do
{
exception = null;
try
{
try
{
if (ExecutionContext.IsFlowSuppressed())
{
return this.listener.BeginGetContext(this.onGetContext, null);
}
using (ExecutionContext.SuppressFlow())
{
return this.listener.BeginGetContext(this.onGetContext, null);
}
}
// .... the rest
Interestingly enough, this is used in 3 places one of them in SharedHttpTransportManager.
Now all this might look like we have found the issue and it is a bug but I very much doubt it.
My hunch is that there is a process recycling happening in between and the context is lost. The way to prove or disprove this would be to use perfmon to register all process recycles and find out if any was in between.
My solution is basically - which you might not like! - to simply insert an item into a queue (MSMQ or a simple database queue) and have a windows service reading it. With this operation being so important, I would never trust IIS to carry out to the finish.
Hope this is useful to you.
Well - exactly as the question subject states - any ideas on how you might do this?
I've been looking over the objects in System.Web.Hosting but nothing is standing out.
The reason? I'm getting one or two application errors which are typically occuring during a recycle (they happen about 25 hours apart and I've left my app pool recycle time at the default) and so I want to know if they're happening on a thread that's in the pool that's shutting down, or the one that's start(ed/ing) up.
I recently stumbled across this article on Brain.Save() which talks about exactly this issue from the point of view of hosting WCF (he's Steve Maine - A program manager at Redmond on the Connected Servies Division).
They need to be able to do this when a WCF service is hosted inside Asp.Net since they need to be able to shutdown any open listeners so that the WCF engine in the new app domain will be able to open them all up again.
As the article demonstrates, the answer is to implement the IRegisteredObject interface, call ApplicationManager.CreateObject to create an instance of your object and then register it with HostingEnvironment.RegisterObject (all detailed in the MSDN documentation for the interface).
When this object's IRegisteredObject.Stop(bool) implementation is called with false as the parameter, this is notification that the app domain is being shut down and that the object should be unregistered (kind of like a global dispose) with a call to HostingEnvironment.UnregisterObject.
When it's called with true it means you've not unregistered in good time, and that if you don't Unregister immediately, it'll be done for you.
I can certainly use this mechanism to find out, when an exception occurs, if the AppDomain is being killed or not. The nature of the object in question that throws the exception means that if it's not at shutdown, it must be during initial startup.
Equally, however, I may well start looking at this persistence mechanism for some of my other more complicated static information!
The History
The article also explains some of the history, and rationale, of why you would want to use IRegisteredObject rather than Application_Start and Application_End methods in global.asax:
Traditional ASP.NET applications can hook application lifecycle events (application startup/shutdown) by implementing methods like Application_Start and Application_Stop in global.asax. However, global.asax is for application code. Infrastructure pieces (of which the WCF hosting system is one) need a mechanism of hooking AppDomain lifecycle events that do not involve dumping infrastructure code in your global.asax file. That space is reserved for you, the user, and it would be rude of use to pollute that with a bunch of hosting goo we need to make the whole thing work. Instead, the ASP.NET folks did some great work during the Whidbey release to open up the hosting API’s and make it easy for people like WCF to come along and hook these lifecycle events in a way that’s invisible to application code.
You can check the value of System.Web.Hosting.HostingEnvironment.ShutdownReason, when the app pool is not in the process of closing / recycling it will have the ShutdownReason of None.
Adding the actual code to do this:
public class RecycleWatcher : IRegisteredObject
{
public static bool IsRecycling { get; private set; }
public void Register()
{
HostingEnvironment.RegisterObject(this);
}
public void Stop(bool immediate)
{
IsRecycling = true;
}
}
Then enable it by running
new RecycleWatcher().Register();
After that just check that property for IsRecycling to know if you are recyling or not.
if (RecycleWatcher.IsRecycling) DoSomething();
Not sure exactly what you want to do when the appication pool recycles but if you add the below event handler to Global.asax then the code in it will run when the application is shut down.
protected void Application_End(object sender, EventArgs e)
{
}
I have some ASP.NET web services which all share a common helper class they only need to instantiate one instance of per server. It's used for simple translation of data, but does spend some time during start-up loading things from the web.config file, etc. The helper class is 100% thread-safe. Think of it as a simple library of utility calls. I'd make all the methods shared on the class, but I want to load the initial configuration from web.config. We've deployed the web services to IIS 6.0 and using an Application Pool, with a Web Garden of 15 workers.
I declared the helper class as a Private Shared variable in Global.asax, and added a lazy load Shared ReadOnly property like this:
Private Shared _helper As MyHelperClass
Public Shared ReadOnly Property Helper() As MyHelperClass
Get
If _helper Is Nothing Then
_helper = New MyHelperClass()
End If
Return _helper
End Get
End Property
I have logging code in the constructor for MyHelperClass(), and it shows the constructor running for each request, even on the same thread. I'm sure I'm just missing some key detail of ASP.NET but MSDN hasn't been very helpful.
I've tried doing similar things using both Application("Helper") and Cache("Helper") and I still saw the constructor run with each request.
You can place your Helper in the Application State. Do this in global.asax:
void Application_Start(object sender, EventArgs e)
{
Application.Add("MyHelper", new MyHelperClass());
}
You can use the Helper that way:
MyHelperClass helper = (MyHelperClass)HttpContext.Current.Application["MyHelper"];
helper.Foo();
This results in a single instance of the MyHelperClass class that is created on application start and lives in application state. Since the instance is created in Application_Start, this happens only once for each HttpApplication instance and not per Request.
It's not wise to use application state unless you absolutely require it, things are much simpler if you stick to using per-request objects. Any addition of state to the helper classes could cause all sorts of subtle errors. Use the HttpContext.Current items collection and intialise it per request. A VB module would do what you want, but you must be sure not to make it stateful.
I 'v done something like this in my own app in the past and it caused all kinds of weird errors.
Every user will have access to everyone else's data in the property. Plus you could end up with one user being in the middle of using it and than getting cut off because its being requested by another user.
No there not isolated.