Preface: I know this is an unusual/improper way to do this. I can do this with a "real" ShowDialog(), background worker/thread, and so on. I'm not looking for help doing it that way; I am trying to do specifically what I describe here, even if it is ugly. If this is impossible for X reason, please let me know though.
I have created a fancy progress dialog for some of our long running operations. I need to have this dialog shown on a new thread while having processing continue on the calling (UI in most cases) thread.
This has 3 real requirements:
- Prevent user interaction with the calling form (similar to ShowDialog(this))
- Keep the progress dialog above the main window (it can fall behind now)
- Allow the main thread to continue processing
What I have looks like this (and works just fine so far, as far as running goes, except for those issues above):
Using ... ShowNewProgressDialogOnNewThread() ...
Logic
UpdateProgress() //static
Logic
UpdateProgress() //static, uses Invoke() to call dialog
...
End Using // destroys the form, etc
I have tried a few ways to do this:
- ShowDialog() on BackgroundWorker / Thread
- Action.BeginInvoke() which calls a function
- ProgressForm.BeginInvoke(... method that calls ShowDialog... )
- Wrapping main form in a class that implements IWin32Window so it can be called cross-threaded and passed to ShowDialog() - this one failed somewhere later one, but at least causes ShowDialog() to not barf immediately.
Any clues or wisdom on how to make this work?
Solution (For Now)
- The call to EnableWindow is what did what I was looking for.
- I do not experience any crashes at all
- Changed to use ManualResetEvent
- I set TopMost, because I couldn't always guarantee the form would end up on top otherwise. Perhaps there is a better way.
- My progress form is like a splash screen (no sizing, no toolbar, etc), perhaps that accounts for the lack of crashes (mentioned in answer)
- Here is another thread on the EnableWindow topic (didn't reference for this fix, tho)