Search code examples
c#multithreadinguser-controlsdispose

c# dispose UserControl Thread


I have a MainForm with a UserControl. In can chose which usercontrol I want the show in my MainForm. Everytime I change my usercontrol, I dispose it.

    private void buttonBar1_ItemClick(object sender, Janus.Windows.ButtonBar.ItemEventArgs e)
    {
        foreach (Control control in panelMain.Controls)
        {
            control.Dispose();                
        }
        panelMain.Controls.Clear();

        //...

        MyUserControl uc = new MyUserControl();
        MyUserControl.Dock = DockStyle.Fill;
        panelMain.Controls.Add(MyUserControl);  

        //...
    }

On of my UserControls has it's own polling thread. the thread show some rows in a database and refresh itself every second.

    private Thread thread;

    public MyUserControl()
    {
        InitializeComponent();

        ThreadStart job = RefreshGui;
        thread = new Thread(job);
        thread.Start();
    }

    private void RefreshGui()
    {
        while (true)
        {
            //load Data

            Thread.Sleep(1000);
        }
    }       

Now I want the shutdown my thread everytime when I change my usercontrol. I already tried:

Never called:

Dispatcher.CurrentDispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
{
    thread.Abort();
}

There is already a method with the same signature

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        // get rid of managed resources
    }
}

So how can I stop my Thread everytime I change the UserControl. I don't want the stop my thread in the MainForm! The usercontrol should do this work on itself.


Solution

  • I am assuming this is all with WinForms.

    1. You should definitely clear the Controls container before disposing of the child controls.
    2. While you probably could use Dispose, you could also override OnControlRemoved, which would be called when you clear the controls from the container.
    3. You should be able to just place your Thread.Abort() in the OnControlRemoved method. However, using Thread.Abort() should be a last resort (it's NOT like hitting Ctrl-Alt-Del / End Process). You'd be better off checking a condition and then gracefully exiting the thread if at all possible (using a CancellationToken is recommended). You can use a Thread.Join() to block the UI thread if required.
    4. You will need to use Invoke/BeginInvoke to populate anything in the UI from the background thread.
    5. You should look up BackgroundWorker - it is designed for off-thread data loading with WinForms.