Search code examples
c#multithreadinggarbage-collectionpass-by-referenceinstances

How to detect nullification of an object from a working thread inside it


I'm working on a ReloadableCollection that reloads once per second on a background thread inside of it. The problem is that when I nullify an instance of the collection, the thread doesn't stop (because it doesn't know that the instance in which it is working has been nullified).

I have tried multiple things, like using a wrapper for the instance, making ThreadWork method static and providing it the instance at startup (start(this)), setting cancel to false in the destructor of the Collection, ... nothing worked.

An example of the problem can be seen in the code bellow.

My collection class:

class Collection
{
    private const int INTERVAL=1000;

    Thread thread;

    public Collection()
    {
        thread=new Thread(ThreadWork);
        thread.Start();
    }

    private void ThreadWork()
    {
        while(true){ // how to detect when the instance is nullified?
            Reload();
            Thread.Sleep(INTERVAL);
        }
    }

    private void Reload()
    {
        // reload the items if there are any changes
    }
}

Example usage:

void Main()
{
    Collection myCollection=new Collection();

    // ...
    // here, it is reloading, like it should be
    // ...

    myCollection=null;

    // ...
    // here, it should not be reloading anymore, but the thread is still running and therefore "reloading"
}

Solution

  • Write an explicit 'Stop' method. Don't trigger behavior by setting variables or fields to null.

    What happens here?

    Collection myCollection = new Collection();
    var myOtherCollection = myCollection;
    myCollection = null; //Should it stop here?
    myOtherCollection = null; //And now? Both are null.
    
    Collection myCollection = new Collection();
    MyMethod(myCollection);
    myCollection = null; //And here? What if MyMethod adds the collection to a list, or keeps track of it?
    
    void Test()
    {
        Collection myCollection = new Collection();
    } //Should it stop reloading when we exit the method?
    

    Simply tell the collection to stop reloading when you're done with it. You'll avoid far more headaches, I promise.

    private volatile bool _stopping;
    private void ThreadWork()
    {
        while (!_stopping)
        {
            Reload();
            Thread.Sleep(INTERVAL);
        }
    }
    
    public void Stop()
    {
        _stopping = true;
    }