Search
Close this search box.

Dispose of a WPF UserControl (ish)

I’ve been playing with WPF a little bit, and quite frankly got a bit stuck, (Meh! Who’d have thought).
The problem is as follows:

I create a UserControl – we’ll call it ‘MyUserControl’ (wouldn’t want to break traditions now would we). In said user control I have a button, that when pressed will fire off a new thread. This new thread will (say) poll a file / service – whatever – every 10 seconds or so, and update a Label accordingly. When I close the app, if the app is polling, then the app won’t actually die, basically because the thread that is doing the polling doesn’t know to stop.

So, we have our polling code:

1:    public void PollService()
2:    {
3:      while(Polling)
4:      {
5:        string result = Service.Poll();
6:        UpdateLabel(_lblResults, result);
7:      }
8:    }

with UpdateLabel defined thusly:

1:    private void delegate UpdateLabelDelegate(Label label, string text);
2:    private void UpdateLabel(Label label, string text)
3:    {
4:      if(!Dispatcher.CheckAccess())
5:      {
6:        Dispatcher.Invoke(DispatcherPriority.Send, new UpdateLabelDelegate(UpdateLabel), label, text);
7:        return;
8:      }
9:     
10:      label.Content = text;
11:    }

We also have a property: Polling, which is used to control wether the control is polling the service or not:


1:    public bool Polling {
2:      get { return _polling; }
3:      set
4:      {
5:        _polling = value;
6:        if(_polling)
7:          new Thread(PollService).Start();
8:      }
9:    }

As you can see, when Polling = true; is called, a new Thread is spun off to do the polling. So, in theory (and in practice actually), if we have a Window with a ‘MyUserControl’ instance on it (called _myUC), we can call:

  _myUC.Polling = true;

to start polling, or

  _myUC.Polling = false;

to end polling.

Now, this is great, if I shut down the window when Polling == false, the app will shut down fine. If Polling == true though, well, that’s a different kettle of fish altogether, the thread keeps running in the background leaving the app running (albeit in a hidden stylee). Now, normally, in a WinForms app, I would simply implement IDisposable and do something like:

   1:    public void Dispose()
   2:    {
   3:      Polling = false;
   4:    }

Then I’d know my control would bog off as I want it to.
“So implement already!” – I hear you say. Wish I could, but WPF doesn’t use IDisposable, sooooo what to do?

Right, what’s next on my hit list? Closed? Closing? OnClosing? OnClosed? Gah! None there!!
In fact none of the events on the control are of any use. The only one that sounded plausible was ‘Unloaded’ which (I incorrectly) presumed would be raised when the Window closed. No such luck!

Googling for terms such as: “WPF Dispose Control“, “WPF Dispose UserControl“, “Why the F**k can’t I dispose“, “WPF IDisposable” all come up with nothing of any use (aside from the fact that WPF doesn’t support IDisposable). Erm, right, time to take the battle to the IDE…

 this.

   [ Scroll up ]
   [ Scroll down ]
   [ Hover tentatively over Dispatcher ]

hmmmm… well, why not…

this.Disp [CTRL+ENTER]
 System.Windows.Threading.Dispatcher

 Argh NO! Damn you intellisense!!!

  [ CTRL+Backspace ] x lots

 D i s p a t c h e r .

 Thats better…

   [ Scroll down ]

What’s this??? ‘ShutDownStarted’ an event about shutting down? Ok, it’s for the Dispatcher to shut down, but when the Window is closed, well, that’s what is gonna happen… right? May as well try it, it’s not gonna hurt after all… So, into the constructor we get:

   1:    public MyUserControl()
   2:    {
   3:      /* init code */
   4:      Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
   5:    }

which in turn (via the *wonders* of intellisense) generates:

   private void Dispatcher_ShutdownStarted( object sender, EventArgs e )
   {
   }

Can it be? I put my faithful:

Polling = false;

code in, cross my fingers, and F5 that bad boy….

Compiled (good start)
Running (good going)
Start polling (Poll going)
Close app (…….)

App closed.
Holy fig rolls batman! The thread has been stopped! Setting a breakpoint on the Polling = false; line does indeed show it getting hit when the form is shut… So the next time the erroneous thread runs, it realises Polling does in fact == false, and stops.

Conclusions

To be honest, this is a bit, well, sh!t, and I’m convinced there are better ways of achieving this goal. However, having said that, I’ve had no joy in google or numerous forums. Hopefully someone can point out the errors of my ways (and yes, I imagine that seperating the polling logic into another non-wpf class would do it – but I wanted to see if I could do it this way!!).

This article is part of the GWB Archives. Original Author: XClave

Related Posts