views:

153

answers:

5

Sorry if this has been answered elsewhere... I have found a lot of posts on similar things but not the same.

I want to ensure that only one instance of an object exists at a time BUT I don't want that object to be retained past its natural life-cycle, as it might be with the Singleton pattern.

I am writing some code where processing of a list gets triggered (by external code that I have no control over) every minute. Currently I just create a new 'processing' object each time and it gets destroyed when it goes out of scope, as per normal. However, there might be occasions when the processing takes longer than a minute, and so the next trigger will create a second instance of the processing class in a new thread.

Now, I want to have a mechanism whereby only one instance can be around at a time... say, some sort of factory whereby it'll only allow one object at a time. A second call to the factory will return null, instead of a new object, say.

So far my (crappy) solution is to have a Factory type object as a nested class of the processor class:

class XmlJobListProcessor
{
    private static volatile bool instanceExists = false;

    public static class SingletonFactory
    {
        private static object lockObj = new object();

        public static XmlJobListProcessor CreateListProcessor()
        {
            if (!instanceExists)
            {
                lock (lockObj)
                {
                    if (!instanceExists)
                    {
                        instanceExists = true;
                        return new XmlJobListProcessor();
                    }
                    return null;
                }
            }
            return null;
        }
    }

    private XmlJobListProcessor() { }
    ....
    }

I was thinking of writing an explicit destructor for the XmlJobListProcessor class that reset the 'instanceExists' field to false.

I Realise this is a seriously terrible design. The factory should be a class in its own right... it's only nested so that both it and the instance destructors can access the volatile boolean...

Anyone have any better ways to do this? Cheers

A: 

just make one and keep it around, don't destroy and create it every minute

"minimize the moving parts"

Steven A. Lowe
I guess really this is all as a terrible way to limit resource use on a server. I want to limit the number of instances to one, but ensure that it is only being used in one thread at a time (since the processing can be triggered off every minute), this is why I wanted to avoid the singleton pattern... I DO want one instance at a time but only accessible to one thread at a time... the factory idea was simply something like "if one already exists, you cant have another instance... come back in another minute and try then...".
Also, by not retaining instances when they aren't needed (which is ~70% of each minute period probably), the memory is freed for other things.
I can't imagine that you are 'freeing' up much at all. Think of it like stopping and starting your car. you can leave your vehicle running at idle for a longer period of time than if you continuously stop and start it. The analogy is that it takes 'more work' to stop and start something. Everytime you kill the instance, it goes under GC scrutiny...that takes time away from the GC doing some 'more important'.
dboarman
@[oolong-singy]: on most modern platforms, memory allocation and destruction are the most expensive operations to perform. Unless your singleton takes up several megabytes (and maybe even if it does!), you're probably better off leaving it idle. If single-threading is the primary concern, use a semaphor or lock.
Steven A. Lowe
A: 

I would instance the class and keep it around. Certainly I wouldn't use a destructor (if you mean ~myInstance() )...that increases GC time. In addition, if a process takes longer than a minute, what do you do with the data that was suppose to be processed if you just return a null value?

Keep the instance alive, and possibly build a buffer mechanism to continue taking input while the processor class is busy. You can check to see:

if ( isBusy == true )
{
     // add data to bottom of buffer
}
else
{
     // call processing
}
dboarman
Hmmm, seem you have have a similar view to above... all good learning. :D. As for "what do you do with the data that was suppose to be processed if you just return a null value?" ... There's no data, it's more like "perform the same task X, if it's not already running", where to perform that task, I instantiate a class and call one of it's methods.
Could I just make the class static, give it a static class locking object and then make the "perform task" method something like:public static void ProcessList(SPList xmlJobList) { lock (lockObj) { ... do stuff } }.I guess this will just stack waiting threads up if processing time goes past a minute. But when the next waiting thread takes the lock, there will be nothing left to do since the task is of the type "for every unprocessed item in this list, process it..."
Well, my understanding of 'lock(myObject)' is used for multi-threading purposes. Static instance infers thread safety if I'm not mistaken. I would just instance the processing class, and implement a `bool IsBusy`.
dboarman
my previous comment sucked...I see that you are multi-threading. Are you threading manually, or (my preference) using a .BeginInvoke(...)???
dboarman
Like I said, a system outside of my control (Sharepoint Timer service) is triggering the multi-threaded requests. I have no control over the thread creation. All I'm trying to do is constrain the possibility of multiple threads trying to access the same object. At least, I'm assuming that SP is triggering the requests on new threads....
ah...ok...I need to read more carefully :/
dboarman
A: 

I take everyone's point about not re-instantiating the processor object and BillW's point about a queue, so here is my bastardized mashup solution:

public static class PRManager
{
    private static XmlJobListProcessor instance = new XmlJobListProcessor();
    private static object lockobj = new object();

    public static void ProcessList(SPList list)
    {
         bool acquired = Monitor.TryEnter(lockobj);
            try
            {
                if (acquired)
                {
                    instance.ProcessList(list);
                }
            }
            catch (ArgumentNullException)
            {
            }
            finally
            {
                Monitor.Exit(lockobj);
            }
    }
}

The processor is retained long-term as a static member (here, long term object retention is not a problem since it has no state variables etc.) If a lock has been acquired on lockObj, the request just isn't processed and the calling thread will go on with its business.

Cheers for the feedback guys. Stackoverflow will ensure my internship! ;D

+1  A: 

Your original example uses double-check locking, which should be avoided at all costs.

See msdn Singleton implementation on how to do initialize the Singleton properly.

Chris O
Best article on C# singletons I've seen yet is: http://www.yoda.arachsys.com/csharp/singleton.html
+1  A: 

I know .NET 4 is not as widely used, but eventually it will be and you'll have:

private static readonly Lazy<XmlJobListProcessor> _instance =
    new Lazy<XmlJobListProcessor>(() => new XmlJobListProcessor());

Then you have access to it via _instance.Value, which is initialized the first time it's requested.

280Z28
oooh, sounds sweet. I WOULD be using it if it weren't for the fact that I'm doing SharePoint 2010 beta 2 development, and it has "issues" regarding targeting .NET 4. Sigh. Good to know though mate. :D