I have a question about Singletons running within IIS (6,7,7.5) and an ASP.NET 4.0 Web Application (MVC3 app to be specific).
I have a singleton object in my project that is accessed and used in the global.ascx, on the application_start, as well as a few other places within the application.
My concern is, this singleton needs to be accessable at a per instance scenario. However, since IIS is essentially the hosting process, is the singleton going to be the same object across all instances of the application?
If I use the [ThreadStatic] keyword, does it seperate at the Application Pool level?
Finally, is there a way, I can assure a singleton is only a singleton per instance of my application. i.e. if I run my application on 1 website, but inside 5 virtual directories, there is 5 instances of the singleton or if I run my website on 5 different websites within the same application pool.
Hopefully that's clear enough, incase you wanted to see the singleton object, I pasted the general idea of it below.
public sealed class Singleton : IDisposable
{
[ThreadStatic]
private static volatile Singleton _instance;
[ThreadStatic]
private static readonly object _syncRoot = new object();
public bool IsReleased { get; private set; }
public Singleton()
{
IsReleased = false;
}
public static Singleton Instance
{
get
{
if (_instance == null)
{
lock (_syncRoot)
{
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
public void Dispose()
{
IsReleased = true;
Singleton._instance = null;
}
}
A static value should be static across a particular instance of your web application, so each instance of your application will have its own instance that will be shared across all threads on that instance.
For further reading, see http://msdn.microsoft.com/en-us/library/2bh4z9hs(v=vs.71).aspx
Oh, and the ThreadStatic attribute will cause the static value to only be static across a particular thread, so every request would have its own version of that field. It doesn't sound like this is what you're going for.
With IIS, you have no control over the thread that your request runs on. If you really need this kind of application instance level locking, you may want to look into the heavier locking objects (Mutex, Monitor, etc) and create one for each application.
If you absolutely want to ensure that they are separate, you could run each one in it's own Application Pool. That way you'd get a WP for each virtual directory.
Related
I need to provide an api to a long running windows service which does a bunch of processing and retains a memory of that history. An api is required to provide status on current activity levels of the system (records processed, records waiting to be processed, etc).
I was wanting to use a self-hosted Owin ApiController to provide a nice interface to the system. However, the ApiController is completely stateless and there is no method (after searching dozens of IoC posts) for injecting an already active instance into the controller.
Is there a way to provide a class instance to an ApiController?
I don't think you can inject an old instance of the controller, because you get a new instance every time you perform a request.
However you can create a singleton object with a collection inside, and you can inject it into the controller constructor and use in every request.
You can also use some sort of persistence such as DB, that you can run on your device.
Here is an example for a singleton class:
using System;
public class Singleton
{
public Dictionary<string,object> State {get; private set;}
private static Singleton instance;
private Singleton() {
State = new Dictionary<string,object>();
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
Even though you can get Session state in web api controller, it is going to be questionable solution, instead, I would recommend going the following way:
include Hangfire as dependancy and use it for long running tasks
Use signal-r to to push state of background task
return JobID from your API method and use it on the client to subscribe to signal-r hub
In a couple of .NET C# webservice projects that i have done i have made access to db static with help of the singleton pattern. Then the other day my friend told me that this is a bad thing to do, because if a lot of request is made for the same db entity then the db would be locked because of the static instance. Is my friends assumptations right? I thought that every new request would make a new instance of the class?
The implementation of the singleton class looks like this:
public class WebService
{
private readonly IFactory _factory;
public WebService(IFactory factory)
{
_factory = factory;
}
public IDataRepository Data
{
get
{
return _factory.GetDatabase();
}
}
}
public static class WebServiceImpl
{
private static readonly WebService _webService = new WebShop(new WebserviceFactoryImpl());
public static WebService webService { get { return _webService; } }
}
_factory.GetDatabase() returns a new instace of the Database class.
Looking at WebServiceImpl, all calls will be sharing a single WebService instance. Now, this isn't necessarily a problem, depending on how that is implemented; for example, if _factory.GetDatabase(); ends up getting called per-request, then it might be that you are getting away with it. Depending further on what GetDatabase() does - i.e. does it get a new instance per call? or does it give you the same instance every time? Simply: we don't have enough information there to answer fully. But:
sharing a single database connection between requests is dangerous; either you need to lock / synchronize, or you risk lots of errors (database connections are not usually written to be thread-safe)
sharing an ORM between requests is even worse: in addition to everything above, you also get issues with data accumulating in the identity / object cache; ORM instances (data-context, etc) are intended to be short-lived and then discarded (and sometimes: disposed)
Having static access to the database is not necessarily a problem; it all comes down to how that is implemented - for example, a static-based API could still create (and dispose) a connection on every call.
Background/Question:
I'm fairly new to the singleton design pattern. I've used it once in a web application (with the help of the SO community):
public static AppGlobal Instance
{
get
{
if (HttpContext.Current.Session != null)
{
HttpSessionState session = HttpContext.Current.Session;
if (session["AppGlobalInstance"] == null)
{
session["AppGlobalInstance"] = new AppGlobal();
}
return (AppGlobal)session["AppGlobalInstance"];
}
else
{
return null;
}
}
}
The above implementation makes sense to me because the instance of the AppGlobal is stored in the session. When the session dies, AppGlobal dies. What happens if I use the same design pattern in a class library that is called by a web application? For example, the users requests a page that calls methods in a DLL that doesn't know about the session. Will the data stored in the singleton instance be persisted through multiple calls?
private static readonly Singleton instance = new Singleton();
private Singleton() { }
public static Singleton Instance
{
get
{
return instance;
}
}
Additional Information:
Here's what I'm trying to accomplish: I have a web application that is going to receive XML requests from a third party application. This XML will tell my web application to do one of three things (or all three of them). I would like to have a singleton instance of a class that stores data that can be accessed by multiple classes. I want the singleton instance to DIE after each request. If the above doesn't accomplish this, what's the best way to accomplish it?
Note: This web application runs on a single server and will never run on a farm.
EDIT 1:
Based on the suggestion below, I've used System.Web.HttpContext.Current.Session to store my class instance. Does this look like the correct approach for a singleton that will be unique to each session (remember I'm in a class library)?
public static Ariba Instance
{
get
{
if (HttpContext.Current.Session != null)
{
HttpSessionState session = HttpContext.Current.Session;
if (session["AribaInstance"] == null)
{
session["AribaInstance"] = new Ariba();
}
return (Ariba)session["AribaInstance"];
}
else
{
return null;
}
}
}
It will be persisted through multiple calls, but there is one caveat. The static variables are scoped to the AppDomain, so any time the IIS worker process is recycled, any data stored in a static variable will be lost. The same is true of session data, if you're storing it "in proc."
If you want an object that will only exist for the duration of the HTTP request, you can use the HttpContext.Items property.
Because the singleton is static, your data will be available for all the requests in your web application, so it will not be available only for the session.
But in ASP.NET applications, you should avoid using Singletons. Instead you should use the Application object. Main reason for that is that if you will use a web farm then your singleton is no longer singelton for the application scope but only on the machine.
Oh!
If you want to use the instance PER REQUEST, why don't you pass it as a parameter to the methods you are calling or as a constructor parameter for the classes that requires the xml. This will be the best design approach, I think.
I have some WCF services. These services run in ASP.NET. I want these services to be able to access a static variable. My problem is, I'm not sure where the appropriate server level storage mechanism is. I don't want to use the database because of speed. But, I want the static variables to stay in memory as long as possible. In fact, I'd like it to stay until I restart my server if it all possible.
Can anyone provide me with any ideas?
You could use static variables in WCF but you must properly synchronize the access to them because they can potentially be accessed from multiple threads concurrently. The values stored in static variables are accessible from everywhere in the AppDomain and remain in memory until the server is restarted.
You could have something like this
public static class StaticVariables
{
private static string _variable1Key = "variable1";
public static Object Variable1
{
get
{
return Application[_variable1Key];
}
set
{
Application[_variable1Key] = value;
}
}
}
The Application collection itself is thread safe but the stuff you add to it might not be; so keep that in mind.
If all the services are in a single ServiceContract and if all the member variables in your service can be shared across all sessions, then you could set the ServiceBehavior to have a single instance.
[ServiceBehavior( InstanceContextMode = InstanceContextMode.Single )]
public class MyService : IMyServiceContract
{
}
I am attempting to create a singleton service that is used to process incoming requests to an HttpHandler. At the moment the service is being instantiated on every request. I make a call to the static class that holds an instance of the service, implemented as a singleton as below:
public static class ServerApplication {
static Service instance = null;
static readonly object padlock = new object();
/// <summary>
/// Service singleton.
/// </summary>
public static Service Service {
get {
lock (padlock) {
if (instance == null) {
instance = new Service();
}
return instance;
}
}
}
And access it using a call as below in the HttpHandler:
ServerApplication.Service.Process(request);
I have set a breakpoint on the instance = new Service(); line and with multiple requests the
breakpoint is triggered per request.
My aim is a service that exists across requests as it loads and caches lots of data from files and databases that is reused with most requests.
Can anyone see what is going wrong?
A couple of things:
If it's a multiprocessor box, technically, you should mark the shared service instance with the "volatile" keyword or use a call to MemoryBarrier (see http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx). You didn't specify architecture, so hard to say if this is really the issue, but better safe than sorry.
You should implement a double-check lock (eg, check for null both before and after acquiring the lock on "padlock"). This way you're doing a much cheaper comparison instead of acquiring a lock on all the subsequent reads.
That should cover you on the concurrency fronts. It's also possible (though less likely) that your AppDomain is being unloaded between requests (ie, you wrote a file inside the web directory causing ASP.NET to think your app is stale), which would cause the statics to be reset.
HTTP is designed to make several concurrent connections, I don't know that you'd want to break this, unless you make very few connections on page loads. That said, perhaps you could keep the HttpHandler in the Session?
Generally speaking, if you want a singleton - cannot see if its necessary i usually implement it this way: http://www.vikingworks.dk/page/Creating-a-Singleton-Pattern-i-C.aspx