Closing openFileDialog

curlydog

Well-known member
Joined
Jul 5, 2010
Messages
50
Programming Experience
Beginner
I have a form on which the user selects a file using an openFileDialog. The selected filepath is then processed, which may take 10-20 seconds before the user is presented with the results.

I'm finding that the once the user selects the file (clicking the OK button on the openFileDialog), the openFileDialog remains open until all of the processing going on in the background is completed. Once the processing has finished the openFileDialog disappears and the results are shown.

The problem is that whilst the openFileDialog remains open on screen, it is not apparent to the user that anything is happening in the background. I do actually have a textbox which updates the user with messages showing the progress. However the openFileDialog hides the messages until it closes, essentially making the progress messages useless.

What I'm trying to do is have the openFileDialog close immediately that the user selects a file. Then the processing can continue without the openFileDialog obscuring my form.

I'm sure there's a simple solution, but this if my first attempt at forms and I can't find it. Any suggestions would be greatfully appreciated.

Jason
 
You should not do any significant processing or blocking of the UI thread, 10-20 seconds is very much so I'd say. .Net makes multithreading easy, try for example the BackgroundWorker component that can be found in Toolbox. You will find that once you delegate the processing to a secondary thread the dialog is dismissed right away and the UI remains responsive. You can for example use a ProgressBar to show progress indication, also for indetermined progress, in addition to passing messages to be displayed in UI if you wish. The BackgroundWorker has functionality that simplifies passing progress and other information back to the UI thread. Give it a try, and check with documentation and/or web resources if you need to.
 
Thanks for your response John.

I've taken you advice and used a background worker to handle the prosessing in the background. I had a little trouble having the background pass messages back to UI.

I've spent the past two days researching the problem (hence the delay in replying) and redesigning my application in order to get round the problem. It has worked with limited success!

I now have a dedicated class to handle my event arguments (ProgressBarProgressEventArgs). I have also created a class which handles the main control of the application (MainControl) which act as a buffer between the UI and the classes actually doing the work. The UI creates a backgound worker which then calls routines in the MainControl class. The MainControl class in turn creates further classes which conduct the processing.

One of my classes is called File. Amongst other things it reads user selected file into an array which contains individual words. It then loops through the array and 'cleans' the words befor inserting them into a database. This is the process that takes the time and where I want to update the user as to the progress, both in terms of a progress bar and messages.

The flow of the application is the form creates a new MainControl object which in turn creates a new File object where the work is done. My MainControl class raises events depending on the arguments it receives. My form has a handler for the events. My File class inherits the MainControl class in order that it can raise events contained in the MainControl class.

What I'm finding is that when I raise an event from the File object, it is not handled on the form. When I raise an event from the form, the event is handled. I'm stuck here as I don't understand why only the events raised from the form are handled, even though both the File and Form objects are using the same routines in the MainControl object.

Here's and example of the code I'm using.

From my backgroundWorker.DoWork routine
VB.NET:
Dim mc as New MainControl
mc.currentProgress ("This message raises and event from my form")
This event is handled as I would expect.

From myFile object (bearing in mind it inherits my MainControl class)
VB.NET:
currentProgress("This message raises an event from my file object")
This event is not handled.

Through my debugging code I can see that when my File object causes the event to be raised the following happens.
The MainControl routine (currentProgress) receives the string. It then creates an object of my ProgressBarProgressEventArgs class and the message is set as a property. It then raises the event (using RaiseEvent).

It appears though that this event is not seen by the handler on my form.

I'm sorry for the long winded explanation, I'm sure there's a simple explanation, but I've spent two days trying to figure it out and I'm still stuck. I just can't understand why events originating from the form are handled, but events originating from other classes are not, even though they both access the same method in order to raise the event.

Many thanks
Jason
 
I think (more like guessing) that your other events are raised from secondary thread - and access UI elements which therefore throws exceptions - which is swallowed by BackgroundWorker. The key functionality of the BackgroundWorker, apart from providing a background thread, is the simplicity it provides to reporting back to UI thread, this is done using the ReportProgress method that raises the ProgressChanged event in UI thread, and the e.Result object that you can pass to RunWorkerCompleted event which is also raised in UI thread. You can pass any object both with each call to ReportProgress and to the final Result object. BackgroundWorker basically has one additional feature, that is the cancellation functionality. This is all included as a basic multithreading package to provide the simplest interface possible to managing a background thread in a forms environment. So if you're not using the BackgroundWorker reporting and it's UI events you might just as well create a background thread yourself (or get one from pool) and use Control.Invoke to report back to UI thread, but I recommend you learn a little more about using BackgroundWorker first adn see if that component will be sufficient for your needs.
 
Hi John,
I resolved this issue after yet more research.

In my MainControl class, in which I have routines raising events, I had the line
VB.NET:
Public Event reportProgress as ProgressBarHandler

I changed it to the following and everything worked as expected
VB.NET:
[B]Shared [/B]Event reportProgress as ProgressBarHandler

Many thanks for your advice.
 
There is a significant difference between a shared event and an instance event, and neither has anything to do with threads. They both will behave exactly the same in any thread contexts, the event handlers are called in the thread that raises the event.
 
Back
Top