2

I have seen many questions on SO regarding the disposal of a BackgroundWorker in a Windows Forms application, and it appears that the consensus is that they do not need to be manually disposed in most situations. However, I have a question regarding how to handle a UserComponent that is being disposed when a BackgroundWorker is actually running. (IsBusy returns true) Should this situation be handled in any particular way?

For example I have a UserControl (panel-like object) that a user can enter settings information. It contains a BackgroundWorker in it that saves a user's configuration. When the panel looses focus (Leave event) it spins up the BackgroundWorker if it's not already running to save the configuration to file if a change is detected. Since the Leave event may also be the user changing to another screen this panel will now be disposed. If the BackgroundWorker is still running do I need to handle this in the Dispose method of the UserComponent itself?

JNYRanger
  • 6,829
  • 12
  • 53
  • 81

1 Answers1

4

It depends, we can't see your code. First off, it is pretty unlikely that you can implement CancelAsync() so don't bother with that. Spinning until IsBusy returns false in the Dispose() method is an option, but do beware of deadlock. You'll definitely get one when you implemented an event handler for RunWorkerCompleted. It is unlikely you have one so spinning ought to be okay.

The sane approach is to just let it run. The user will be happy. Some precautions are necessary:

  • The worker thread should still be able to access the properties of the control even if it was disposed. This is not normally a problem, you store the values of simple backing variables, they don't become invalid when the control is disposed. Easy to test btw, but if you are not sure then using a simple class that stores the values that need to be preserved and passing it to RunWorkerAsync() is always safe.

  • You need to deal with the risk of the worker thread being aborted because the program terminated. If that happens just as it is writing the file then the file will get corrupted. You solve this by writing to another file instead. And using File.Replace() to swap it. In general always a strategy you should use when you replace files.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • The deadlock of spinning is what I'm afraid of, which is what prompted me to ask this question. The data in the UI class doesn't really need to be preserved after the configuration file is written, assuming it isn't corrupted, since it will be re-read in order to populate this panel again if it is accessed again after it's closed. – JNYRanger Apr 10 '14 at 13:22
  • I gave a specific recommendation to avoid it, I suggest you use it. Easy to test, just close the main window with the focus on the control. That triggers Leave, quickly followed by Dispose(). Put Thread.Sleep(3000) in DoWork to be sure. – Hans Passant Apr 10 '14 at 13:32
  • I'm definitely going to; was just providing some background. This can be safely placed in the RunWorkerCompleted handler correct? Or does it need to be kicked off in the dispose method? – JNYRanger Apr 10 '14 at 13:35
  • No, you spin in Dispose(). As I mentioned, you'll deadlock if you implemented RunWorkerCompleted. I have to say, you not posting your code makes this unnecessarily difficult. Please close your question. – Hans Passant Apr 10 '14 at 13:45
  • 1
    Forgive me for asking for clarification, no need to be rude. I figured the question was general enough that a SSCCE wasn't needed, sorry. – JNYRanger Apr 10 '14 at 14:43