How to Invoke when form is hidden?

  • Thread starter Thread starter Altramagnus
  • Start date Start date
A

Altramagnus

I have a main thread which creates all my forms.
All my forms are hidden initially.
After that, I have some worker threads which will call BeginInvoke
to update and show the necessary forms.
However, it throws an exception saying that a handle is needed to be
created in order to use Invoke or BeginInvoke.
But the handle is only created when the window is first visible!!!!!!!!
How then can I update and show the form when it is initially invisible??????

Somebody please HELP!
This .NET problem is killing me!
NOTE: JAVA HAS NO SUCH PROBLEM!!!!!
Why tie a window to a thread!?!?!?
Why create a handle ONLY when it is visible?
 
Altramagnus,
NOTE: JAVA HAS NO SUCH PROBLEM!!!!!
Then use Java! ;-)
Why tie a window to a thread!?!?!?
Its a Win32 limitation, System.Windows.Forms is based on (thin wrappers of)
Win32 Windows.
Why create a handle ONLY when it is visible?
You can use Control.IsHandleCreated to see if the handle is created yet or
not. You should be able to use Control.CreateControl to create the handle,
if its not yet created.

My concern would be using CreateControl from a worker thread, as that may
cause the BeginInvoke to need to be handled on the worker thread and not the
main thread. I have not actually used forms on multiple threads, so I'm not
sure what will happen... I would probably simply call CreateControl on the
main thread, so there's no question.

Hope this helps
Jay
 
I did try calling CreateControl
But the handle is still not created if it is invisible.
so it is still a problem.
I have to call .Show() or Visible = true in order for the handle to be
created.
 
Jay B. Harlow said:
Altramagnus,
Then use Java! ;-)

Yes I would love to.
But it is not up to me to decide.
My customer insist on C#


Its a Win32 limitation, System.Windows.Forms is based on (thin wrappers of)
Win32 Windows.




You can use Control.IsHandleCreated to see if the handle is created yet or
not. You should be able to use Control.CreateControl to create the handle,
if its not yet created.


I tried this:

Form f = new Form();
Console.WriteLine( f.IsHandleCreated );
f.CreateControl();
Console.WriteLine( f.IsHandleCreated );
f.Show();
Console.WriteLine( f.IsHandleCreated );

Output is:
false
false
true

so handle is only created when it is first shown.
 
* (e-mail address removed) (Altramagnus) scripsit:
I have a main thread which creates all my forms.
All my forms are hidden initially.
After that, I have some worker threads which will call BeginInvoke
to update and show the necessary forms.
However, it throws an exception saying that a handle is needed to be
created in order to use Invoke or BeginInvoke.
But the handle is only created when the window is first visible!!!!!!!!
How then can I update and show the form when it is initially invisible??????

In this case 'Control.InvokeRequired' will return 'False' and you can
access the controls directly. Nevertheless, you will have to make sure
that the state of the UI doesn't change (the form is not shown), because
this may require to use invoke.
 
Herfried K. Wagner said:
* (e-mail address removed) (Altramagnus) scripsit: invisible??????

In this case 'Control.InvokeRequired' will return 'False' and you can
access the controls directly. Nevertheless, you will have to make sure
that the state of the UI doesn't change (the form is not shown), because
this may require to use invoke.

Thanks for the info.
I did not realize that Control.InvokeRequired will return False when handle
is not created yet.
This solves the updating part. But I am required to show the form after
updating.

When the form is initially hidden, the handle is not created, I could not
call invoke from a worker thread
to show it, because without a handle, invoke cannot be called.
I could not call .Show() directly from the work thread either, because that
will tie the window to my worker thread.

Then how do I change the visibility with my worker thread ( intially hidden
when handle is not created )?
why can't we force the handle to be created when the form is invisible?
Isn't that what the CreateControl() should do?


Thanks.

 
Hi,

An alternative solution to calling Invoke would be to raise an event and
have your forms do what they have to do in the event handler. The event
machinery will cope with thread marshalling issues.

HTH

FM
(e-mail address removed)
 
Altramagnus,
Its nice to know that Control.CreateControl, doesn't actually create the
handle, as MSDN would suggest it does...

Now I'm curious on when one would actually use Control.CreateControl.

I'll see what I can find out.

Hope this helps
Jay
 
Altramagnus,
I did some experimenting.

If you call Form.Handle, the handle will be created for you.

Debug.WriteLine(form.IsHandleCreated, "IsHandleCreated")
Debug.WriteLine(form.Handle.ToInt32(), "Handle")
form.CreateControl()
Debug.WriteLine(form.IsHandleCreated, "IsHandleCreated")
Debug.WriteLine(form.Handle.ToInt32(), "Handle")

If I take out the calls to form.Handle, I get the effect you describe, if I
leave them in the handle is created. I am checking on when you would
actually use CreateControl, as it appears (as you stated) not to do anything
for a Form.

FWIW: I used "form.Handle.ToInt32()" to avoid the debugger from displaying
the value of the Handle itself, invalidating my test...

Hope this helps
Jay
 
How do you raise an event from another thread to the thread that ties to the
window?

Thanks.
 
I understand your frustation

After beating my head against this one too, I did the following in the constructor for my application:

MyHiddenWindow myWin = new MyHiddenWindow(blahblah);
myWin.Handle.ToInt32();

This constructed the handle in the correct window, so elsewhere in the app (in MyHiddenWindow's event handler for something fired from a FileSystemWatcher)...I could do...

if(InvokeRequired)
this.BeginInvoke(blahblahdelegateformymethod);

and in blahblahdelegateformmymethod...I do this.Show();
And voila, my previously hidden form has a real live message loop inherited from the systray parent window (or whatever other object you're passing to Application.Run();
 
Back
Top