-1

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.

wydy
  • 71
  • 12
  • Use [cooperative cancellation](https://msdn.microsoft.com/en-us/library/dd997364%28v=vs.110%29.aspx) – Sriram Sakthivel May 06 '15 at 10:09
  • 1
    It is very buggy code, it is leaking windows badly and uses a bizarre and unworkable mix of Winforms and WPF code. Throwing threads in the mix and risking deadlock and spinning the Abort wheel of fortune just makes it a *lot* worse. Very hard to give proper advice beyond "throw this away and start over". – Hans Passant May 06 '15 at 10:55
  • The whole thing is just a small prototype with 2 panels. A menu panel and a main panel which switch between the different UC's. During the process I realized, that there isn't a way the manage different threads in my UC and I asked here for an input. How I could cancel my thread when the user close the window. It's easy to say, your code sucks, but I would appreciate every useful hint to improve my code/skills. It's just a small prototype, so it isn't really much work to change the whole thing. – wydy May 06 '15 at 11:25
  • 1
    This is a very harmful pattern: `while(true) { ... Sleep(); }`. Replace it with a Timer and do the loading in a Pool thread or a BackgroundWorker. Solves most of your issues. – H H May 06 '15 at 15:34
  • @HenkHolterman That nap shouldn't be there. It should be waiting on a cancellation waithandle instead or something like that. `cancellationToken.WaitHandle.WaitOne(1000)` ? – Sriram Sakthivel May 06 '15 at 15:37
  • Yes, you're right of course. I was thinking about the simple boolean status. – H H May 06 '15 at 15:39
  • @HenkHolterman Nah. Say no to [simple boolean flag](http://stackoverflow.com/a/30025043/2530848) :) – Sriram Sakthivel May 06 '15 at 15:42

1 Answers1

2

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.
MineR
  • 2,144
  • 12
  • 18