Click here to Skip to main content
15,888,579 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi
I encountered a situation where I need a type of follow the singleton pattern, but the type must not be lazy loaded. This is needed becouse I want my instance to be created on the main thread - if lazy loading is used the instance will be created on the thread that first access the instance. Any advice will be appreciated.

Uros
Posted

Actually I don't think this should be a problem. If you are using a singleton pattern you are probably calling a shared method that initializes your object. Even though the object is created on a certain thread this should not prevent it from being accessed from others (unless it's some UI control that is thread bound, but in that case initializing it from the main thread wouldn't solve your 'problem'). As far as I know your object is created on a specific thread, called from specific threads, but stored in the same memory that is thread independant.
Consider the following code:
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // Start a worker thread, initialize the Singleton and set the SomeText Property.
            System.Threading.Tasks.Task.Factory.StartNew(() => SetSingletonText());
            // Simply wait two seconds so we're sure the Singleton instance was set.
            // Don't do this in production code...
            System.Threading.Thread.Sleep(2000);
            // Print the text that was set on a different thread on the main thread.
            PrintSingletonText();
            // Set the text on the main thread.
            SetSingletonText();
            // Print the text that was set on the main thread on the main thread.
            PrintSingletonText();
            // Print the text that was set on the main thread on a different thread.
            // Notice that the console can be accessed from worker threads, unlike, for example, WinForm Controls.
            System.Threading.Tasks.Task.Factory.StartNew(() => PrintSingletonText());
            // Wait for the user the press the 'any' key.
            Console.ReadKey();
        }

        static void SetSingletonText()
        {
            Singleton.GetInstance().SomeText =
                  String.Format("Hello from thread {0}!", System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
        }

        static void PrintSingletonText()
        {
            Console.WriteLine(String.Format("Written on Thread {0}: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, Singleton.GetInstance().SomeText));
        }
    }

    class Singleton
    {
        private static Singleton _singleton;

        public string SomeText { get; set; }

        public static Singleton GetInstance()
        {
            if (_singleton == null)
            {
                _singleton = new Singleton();
            }
            return _singleton;
        }

    }
}
Run it and read the results.
As you can see I can get and set SomeText from any thread. You DO have to make sure your class is thread safe though.
If, for example, you have an integer variable with value 1 and multiply it by 2 from one thread and then add 3 from another thread the order in which the threads access the variable will affect your outcome! If you FIRST multiply 1 by 2 (which is 2) and then add 3 you'll have 5. If you first add 3 and then multiply by 2 you'll have 8. This is also known as a race condition[^].
If you need to synchronize to your main thread from another thread there are also other methods available, depending on how you are starting your thread.
Using a class or method in a multithreaded environment, but only making it work if it was created on some specific thread sounds like a bad idea. Your co-workers may not know your intentions or will even call the method that initializes your object on a worker thread!
For further reading see:
Threading Tutorial (C#)[^]
Thread Synchronization (C# and Visual Basic)[^]

Of course you could still simply call your method on the main thread and hope it will stay that way. It's your call :)
 
Share this answer
 
v2
Comments
koleraba 25-Feb-12 13:27pm    
Thank you for the extensive reply. What my singleton object does is somehow similar to the Dispatcher object found in WPF, but it is meant to be used in windows service enviroment. It's task is to marshal the calls to the thread that created it. That is why I need it to be created on the main thread. Thanks again for the reply, but I think I will go with the static Init() method.
Sander Rossel 25-Feb-12 14:41pm    
Well, if you put it like that, creating it on your main thread seems like the easiest way to do it :)
Write a static method that initializes the instance and call it from the main thread before the class is first accessed.
 
Share this answer
 
Comments
koleraba 24-Feb-12 14:52pm    
That is the obvious solution. But that type is a part of a framework and I did'n want to burden the users of the framework with initialization - I was hoping that it could be done automatically. Thank you for your reply
[no name] 25-Feb-12 1:34am    
I was about to suggest that you initilize the instance in the Type Initializer (aka static constructor), but again it would be called only the first time your class is referenced. That means if the class is first called from a different thread, then the static constructor would be called from the same thread.

Nearling's answer below seems to make sense. Unless you intend to access UI elements (which is not what singleton classes are meant for), you need not worry which thread is calling the class.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900