Question

I have a class named Manager which has a thread. When the application is closed I want to find all instances of Manager to abort their threads. How can I do that?

I already tried Unloaded event in its UserControl but it only works when the UserControl is closed not the whole application.

Now I want to use Closed event of its Window but I don't want to have a Manager reference there. Any idea?

Was it helpful?

Solution

If you set the threads IsBackground property to true, it won't hold up the app terminating on exit

OTHER TIPS

Make the threads a background thread and it will terminate automatically when the program ends. You can set the type of thread via the IsBackground property.

However, I don't consider this as a clean solution. It's cleaner to use a while(!terminate) { ... } loop so that the single threads can finish their tasks, e.g. write into a file. If you just terminate the thread which writes into a file you might end up with corrupt files. This does not only apply to files but other items as well.

Implement IDisposable in your Manager class and ensure that you close and deallocate any resources, such as Threads, in the Dispose method. This will be called when the garbage collector gets around to cleaning up after your application closes, provided you've followed the normal IDisposable pattern as found here:

public class ComplexResourceHolder : IDisposable {

    private IntPtr buffer; // unmanaged memory buffer
    private SafeHandle resource; // disposable handle to a resource

    public ComplexResourceHolder(){
        this.buffer = ... // allocates memory
        this.resource = ... // allocates the resource
    }

    protected virtual void Dispose(bool disposing){
            ReleaseBuffer(buffer); // release unmanaged memory
        if (disposing){ // release other disposable objects
            if (resource!= null) resource.Dispose();
        }
    }

    ~ ComplexResourceHolder(){
        Dispose(false);
    }

    public void Dispose(){
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

Although using IsBackground property would work, to perform additional cleanup, you can use some static members on the Manager class to keep track of the running threads, and loop on that collection when the app exits.

Please take the other answers and comments as a reason to refactor your code and create another solution. However if you have some reason to commit to this, you can create a static list that holds instances to each Manager that can be aborted on exit:

class Manager
{
    //A WeakReference prevents memory leaks when you dispose of managers in another place
    private static readonly List<WeakReference<Manager>> Instances 
             = new List<WeakReference<Manager>>();

    public static void AbortAll()
    {
        foreach (var weakReference in Instances)
        {
            Manager current;
            if (weakReference.TryGetTarget(out current))
                current.Abort();
        }
        Instances.Clear();
    }

    private void Abort()
    {
        //...
    }

    public Manager()
    {
        //...
        Instances.Add(new WeakReference<Manager>(this));
    }
}

Usage:

Manager a = new Manager();
Manager b = new Manager();

Manager.AbortAll(); //calls abort on a and b
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top