Invoking a form that was created on a separate thread

  • Thread starter Thread starter Dan
  • Start date Start date
D

Dan

Hi everyone

I have a class which parses an xml file and creates a form and its controls
from it, and I have recenlty moved this so that it happens on its own
thread, I know about controls that are created on a different thread to the
UI can not just have its methods called without using invoke so with this I
have tried several different ways to get the form to show but I'm having
problems.

The ways I have have tried are:

1. With the form that is returned from the parsing class I have tried
me.invoke(new delegateSub(addressof newform.show))
This throws the error "Cannot call Invoke or InvokeAsync on a control
until the window handle has been created."

2. Add a controller class that is also created on the separate thread which
shows the form when the parsing is complete, this does show the form briefly
but it then disappears.

3. With the same controller class I use Application.Run(parsedform). This
works beautifully apart from one small snag, the class which starts the
parsing is passed a reference to the parser and acts as the code behind for
the the controls that are created in the parsed form e.g. the click event of
a button in the parsed form is handled by a method in the class that is sent
to the parser. This is where this method seems to fall down because the
reference no longer works.

Am I fighting a loosing battle with this or can anyone offer some code of
wisdom.
Any help will be much appreciated.

Many Thanks
Dan
 
The first question has to be why are you creating a Form on another thread?
It's a very bad idea, a bad design, and bad practice.


--
Chris Tacke
Co-founder
OpenNETCF.org
Has OpenNETCF helped you? Consider donating to support us!
http://www.opennetcf.org/donate
 
Hi Chris your right its not good all, the the thing is the xml files that
are being parsed are pretty big and they take quite a bit of time, so I need
to put a progress bar on, I did try creating that on the main the and then
updating that from a separate thread.

If there is a better way to do this I'm open to all suggestions cos this is
p#@*ing me off

Thanks
Dan
 
Check out the BackgroundWorker or do it yourself (parsing on thread and
updating the form with control invoke)

Cheers
Daniel
 
Hi Daniel thanks for that I shall go through your background worker code, I
do currently have a background process implemenation that is based on an
article written by Rocky Lhotka on msdn
http://msdn.microsoft.com/vbasic/us...library/en-us/dnadvnet/html/vbnet09272002.asp
the trouble is the blasted form that is returned from that background
process throws an exception everytime I try and invoke its show method.

Should I be changing the implementation so that I don't do the parsing on
the background thread?

Dan
 
Don't return a form from a background thread. The form should be on the main
form. It is the progress info (percentage and possibly status text) that you
return to the main thread/form from the background thread. With
backgroundWorker you don't need to explicitly invoke anything. Keep your
parsing on the background thread if you have calculated that it takes too
long and hence would block the UI.

Whether you are using the BW from my site (VB version) or from opennetcf (C#
version), the sample here should help:
http://www.danielmoth.com/Blog/2004/12/backgroundworker-sample.html

Cheers
Daniel
 
Hi Daniel

The my problem occurs in that the new form and all its controls only get
created by the parsing routine, its a bit like xaml so all the form
definition is in the xml file that is parsed, So I need to be able to parse
these files which can take a while on the XDA's but still give progress back
and be able to interact with the code behind (the class that instantiated
the parsing) once the form is created and showed.

Sorry if I'm not quite getting this.
Thanks
Dan
 
OK it wasn't clear that you are parsing an XML file to create a form
(XAML-style). I thought you were parsing an XML file for other more
conventional purposes and just needed to report progress to the UI.

I think you are on a loser there. You are going to have to bear the
performance hit for choosing such an approach. Do the form loading/xaml
parsing on the UI thread and stick an hour glass up or some progress bar to
inform the user that they are in for a wait. Basically, trying to do
anything with UI elements on other threads is not supported (unless you come
up with some wacky ideas and I don't have any). How long does it take to
load the form if you just let it run and wait?

Cheers
Daniel
 
Probably about 15 seconds all told, they are surveys that have to be carried
out by engineers on site so they contain quite a lot of stuff.
The only other way I thought about it was using the splash screen example
thats about that runs on a separate thread and instead of it being a
splashscreen it would be the pogress bar.

Dan
 
Sure if you have made the choice that loading your forms this way is worth
the 15 second hit then your only issue is what to show to the user in the
meantime. You could put up a progressbar and use Application.DoEvents
occasionally to help it paint. You could elect to have a launcher app that
comes up first, launches the real app and then sits there with its own
animation/progressbar whatever. You could even put a static message on a
form, then load the other form from xml and when it is ready bring it to the
front...

Cheers
Daniel
 
Hi Daniel

The decision to do the forms this way came about from there being around 15
of the engineer surveys that need to be done and new ones add all the time
so with this all I have to do is create a new xml file each time for a
survey and deploy it to a web server and then when the launcher app is run
it calls a web service to check for new forms and download them and make
them available. It seemed like the best way to cope the dynamisim that
client was after.

I actually managed to get it all working now with my controller class
kicking off the parsing and then showing the form on its own thread and that
form is now calling the methods in the controller that it needs to and then
a proper progress bar is shown during the parsing.

My only problem that I have now goes back to what Chris said at the top of
this thread that doing things like this with forms on threads etc is bad
design, bad practice and I don't like that fact.

Dan
 
Yup, I agree with Chris (as my previous reply indicates). At the end of the
day we have exhausted your options:
1. Don't use xml and lose the flexibility in lieu of performance
2. Use XML on a background thread and be on your own in terms of best
practise and common supported scenarios
3. Use XML on the UI thread and find some way to notify the user that they
should wait

Good luck!

Cheers
Daniel
 
Sorry, but that's the way Windows works. An app should not have more than 1
UI thread, and no other threads can affect UI but that thread. Sure, you
could probably get a second UI thread working, but it requires a separate
message pump for handling all messages for it, and then cross UI thread data
marshalling will be a nightmare, as will synchronization. I'd guess getting
it up and running is a couple months work, and then it's going to be fragile
as hell and I'd never want to be the poor sucker that inherits it for
upgrades and maintenance down the road.

I think you should accept the fact that for total UI flexibility like you
want, a price has got to be paid for loading the definition and creating the
elements. A splash screen, progress bar or animated clown juggling could
provide the user with feedback that something is happening, but it really
needs to be a serial operation.

-Chris
 
Yeah I think I am going to change it so the parsing is done on the ui thread
and then run the progress bar like the splash screen example on msdn, I
don't like the fact that it would be badly designed if it was left the way
it is.

thanks for your help guys.
Dan
 
Back
Top