3

I have a project consisting of three projects,

  1. WCF service
  2. Asp.net MVC 3 application
  3. Class library.

The one in the class library is my singleton, which I have made like this;

public sealed class Singleton
{
    public static Singleton Instance { get; set; }

    private Singleton()
    {

    }

    public static Singleton Instance
    {
        get
        {
            if (Instance == null)
                Instance = new Singleton();
            return Instance;
        }
    }       
}

The thing is, I put a Debug.WriteLinein the constructor, and it gets called twice.
What I am trying to do is use the singleton from the mvc 3 application and from the WCF service, but they make different instances. Why?

EDIT: I tried a treadsafe singleton earlier. It made no difference.

4
  • Your code is obviously not threadsafe, but that should not lead to the constructor being called twice in a reproducable manner. Commented Feb 15, 2012 at 11:16
  • Perhaps your WCF service and your ASP.net application are in different AppDomains. Each AppDomain has its own static variables, and thus its own singleton. And that's necessary, because (most) objects can't be shared between AppDomains. Commented Feb 15, 2012 at 11:18
  • @Hadas That's not correct. What you're suggesting would happen if there was a static constructor (with the logging code in) as well. But .Net will not initialize an instance until one is requested. Commented Feb 15, 2012 at 11:20
  • As a side-note: I'd avoid MyClass.Instance singletons in favour of IoC singletons. | @Hadas what do you mean? Your statement makes no sense at all. Commented Feb 15, 2012 at 11:24

6 Answers 6

3

There's a couple of things that could be going on here.

The most likely is that your MVC application and your WCF service are running in different AppDomains. It will be impossible for the code to 'share' the same instance if this is the case.

An alternative and less likely cause, is that because your code is not thread safe multiple instances are created. If the Singleton constructor takes a long time to return then this could be the issue. Since your using MVC3, I'll assume .Net 4, in which case the Lazy class is your friend:

private static readonly Lazy<Singleton> _singleton = new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return _singleton.Value; } }
Sign up to request clarification or add additional context in comments.

5 Comments

I have tried using a tread safe singleton, but it produces the same results. Is it the AppDomain problem then?
@kjelelokk Read the part about AppDomains again. That's by far the likelier cause.
Now I have a Debug.WriteLine in the constructor, and I only use the singleton in the mvc 3 application. Still gets called twice. Must be something more/else as well.
@kjelelokk Are you using the Lazy<T> class?
Think it si working now, without the lazy as well. Thanks for the help, I tihnk it was the AppDomain thingy;)
1

I guess your implementation is not thread safe. check the article: Implementing Singleton in C#

here a thread-safe example: (there are many other ways to do this, more complex and safer, this is just a reference...)

using System;

public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new Object();

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null) 
         {
            lock (syncRoot) 
            {
               if (instance == null) 
                  instance = new Singleton();
            }
         }

         return instance;
      }
   }
}

1 Comment

+1 for the double check pattern. However, I don't see how any other solution would be safer?
0

I have no experience with WCF, but maybe you should implement a thread safe singleton, see: http://www.yoda.arachsys.com/csharp/singleton.html

1 Comment

That is an old article. New link: csharpindepth.com/Articles/General/Singleton.aspx
0

If the WCF Service is running as a separate application, it will have it's own instance of the singleton as the two applications do not share memory.

Does the WCF Service run on a different IP Address/port number to the MVC application?

1 Comment

Then you will always have 2 instances of the Singleton. One in each application.
0

You can use the lazy pattern in .Net 4.0

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy =
        new Lazy<Singleton>(() => new Singleton());

    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
} 

Source: http://csharpindepth.com/Articles/General/Singleton.aspx

Comments

-1

First, your exact code as posted is not working. It is not syntactically correct (the curly braces are not balanced), and there are two public Singleton.Instance members. I assume your original code was like that:

public sealed class Singleton
{
    private static Singleton _instance { get; set; }

    private Singleton()
    {

    }

    public static Singleton Instance
    {
        get
        {
            if (_instance == null)
                Instance = new Singleton();
            return _instance;
        }
    }       
}

The problem is probably related to a multi-threading environment. That is, while one of threads is calling new Singleton(), another tried to get Singleton.Instance, which, in turn, called another new Singleton().

You should either use double-checked locking there:

public sealed class Singleton
{
    private static Singleton _instance { get; set; }

    private Singleton()
    {

    }

    public static Singleton Instance
    {
        get
        {
            if (_instance == null)
                lock (typeof(Singleton))
                    if (_instance == null)
                    {
                        var instance = new Singleton();
                        _instance = instance;
                    }
            return _instance;
        }
    }       
}

or, much easier,

public sealed class Singleton
{
    public static readonly Singleton _instance = new Singleton();

    private Singleton()
    {

    }
}

5 Comments

Locking on a Type is bad practice.
Well, I tried to do it without the in-place static fields initializers. Anyway, there is no reason to prefer the first way (with locks, be it on a special SyncRoot object or on a Type) over the second one.
I think your first example isn't guaranteed to be thread safe in the EMCA memory model either. | Your second has a potential issue: The instance can be created earlier that expected, since it's a before-field-init class. In most cases this isn't a problem though.
@CodeInChaos, Could you please explain why the first example isn't thread-safe? Is there any possibility that _instance = instance is not atomic?
double ckecked locking requires a strong enough memory model. And I believe the EMCA memory model is too weak, whereas the .net 2.0 model is strong enough.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.