1

I'm trying to create a singleton object which should be in use for each call to my server. But for some reason the static object is keep renew for each call to the Web API. Is there any way to stop it? What can I do?

Thanks for the answers, Here is some code:

The Singleton:

private static CoreEngine _instance;
public static CoreEngine Instance 
    {
        get { return _instance ?? (_instance = new CoreEngine()); }
    }
private CoreEngine(){}

The WebAPI method:

    CoreEngine _coreEngine = CoreEngine.Instance;

    [System.Web.Http.Route("Compare")]
    public void PostCompare([FromUri]string pluginName, [FromUri]string file)
    {
        var plugin = _coreEngine.GetPlugin(pluginName);
        if (plugin == null)
            return;
        plugin.Compare(file);

And a simple client:

 public void Post(string uri, Dictionary<string,string> postDic)
    {


        using (var client = new HttpClient())
        {
            var postUri = FromDictionaryToUriString(uri, postDic);

            var response = client.PostAsync(postUri, null).Result;
        }
    }

Its only one thread and sync. I tried to repeate the same POST method for two times and in the first time I had the first instance of the CoreEngine while in the secound call, The CoreEngine has been disposed and the instance were re-created.

maor david
  • 187
  • 2
  • 14
  • 1
    Hmmm... I don't think that's possible. Are you using a load-balancer WITHOUT sticky sessions? A second-guess would be that an out-of-process exception is occurring, causing your Application Pool to shut down, which then recycles all static/cached/sessioned data – Saturn K Jan 24 '14 at 23:13
  • `static` is *per Application Domain*. If requests are handled on a different app domain then there will be a new singleton object created (since/if workers are re-used there will be cases where the singletons already exist for the request context). A web-application should generally to be designed to share the *data* and not a shared singleton-object. – user2864740 Jan 24 '14 at 23:13
  • How do you initialize _coreEngine in your controller? – Thomas Levesque Jan 25 '14 at 12:00
  • Thomas - `CoreEngine _coreEngine = CoreEngine.Instance` – maor david Jan 25 '14 at 12:30

2 Answers2

3

The short answer is: That's how it's supposed to work. The long answer is already written here.

Community
  • 1
  • 1
Michael Dunlap
  • 4,300
  • 25
  • 36
  • That is true, assuming that he's creating multiple worker processes for one web application. You can find out if you're using multiple worker processes by bringing up task manager and looking for w3wp.exe for the later versions of IIS (aspnet_wp.exe I believe) – Saturn K Jan 24 '14 at 23:15
  • There is nothing in his question that tells us he is working with multiple servers or multiple worker processes... – EkoostikMartin Jan 24 '14 at 23:16
  • No, but a separate thread spawned for multiple requests will yield the same result. A different Singleton. – Michael Dunlap Jan 24 '14 at 23:17
  • @DigitalD Not so. Threads are on the same Application Domain and thus share `static` fields. (I do agree that this - multiple servers/workers - is the likely cause though.) – user2864740 Jan 24 '14 at 23:18
  • @user2864740 They are on the same application domain. But multithreading causes an out of process task to occur so the singleton object WOULD get recreated if this were the case – Saturn K Jan 24 '14 at 23:20
  • @Kant Obscure thread races aside (which should not affect a "long standing" singleton), it seems unlikely that this would cause re-initialization of a singleton - threads share the same static fields. (I'm not sure what an "out of process task" is in context.) – user2864740 Jan 24 '14 at 23:21
  • If it's out of process, it doesn't even have access to session/cache/application/static objects – Saturn K Jan 24 '14 at 23:22
  • 1
    Maybe it's time to wait for an answer to @EkoostikMartin and see some code. – Michael Dunlap Jan 24 '14 at 23:22
0

I tried to replicate this strange behavior and could not. My static variables remained that way across multiple requests. Static objects should be used with care on .NET Web Api as they stay in memory across requests until the App Pool gets recycled. They are also not thread-safe.

A better place exists such as

HttpContext.Current.Application["myKey"] 

Also you can use separate processes similar to Redis.io to maintain a cache on that machine, or across machines.

See Synchronizing Data for Multithreading

Dmitri R117
  • 2,502
  • 23
  • 20