Is this safe

  • Thread starter Michael Chambers
  • Start date
M

Michael Chambers

Hi there,

I have a worker thread that may need to display a dialog for the user. Is it
safe for the worker thread to invoke the form's constructor and then pass
the form's reference to the main GUI thread where "ShowDialog()" will then
be invoked. I assume it probably is since the form is never displayed on the
actual worker thread. Can someone confirm this is safe. Thanks.
 
C

Carl Daniel [VC++ MVP]

Michael Chambers said:
Hi there,

I have a worker thread that may need to display a dialog for the user. Is
it safe for the worker thread to invoke the form's constructor and then
pass the form's reference to the main GUI thread where "ShowDialog()" will
then be invoked. I assume it probably is since the form is never displayed
on the actual worker thread. Can someone confirm this is safe. Thanks.

I don't think you can assume that it's safe. Whether it's safe depends on
whether the dialog's window handle has been created, and exactly when the
window handle is created depend on exactly how the dialog is accessed,
including potentially from code that runs in the constructor of the form.

I'm prepared to be wrong about that :) I suspect that it is in fact safe in
many cases, but I wouldn't bank on it.

-cd
 
B

Brian Gideon

Carl said:
I'm prepared to be wrong about that :) I suspect that it is in fact safe in
many cases, but I wouldn't bank on it.

Carl,

I agree. I wouldn't bank on it either. Plus, if you're already
putting forth the effort to call ShowDialog on the UI thread then why
not instantiate the Form there too.

Brian
 
M

Michael Chambers

I have a worker thread that may need to display a dialog for the user. Is
I don't think you can assume that it's safe. Whether it's safe depends on
whether the dialog's window handle has been created, and exactly when the
window handle is created depend on exactly how the dialog is accessed,
including potentially from code that runs in the constructor of the form.

I'm prepared to be wrong about that :) I suspect that it is in fact safe
in many cases, but I wouldn't bank on it.

Thanks for the feedback. I'm the one who's authoring this form however and
the constructor will always perform simple initialization only (no window
handles are ever created). Since the form is originally created by the VS
form's designer however, I can't be sure what "InitializeComponent()" will
do. I seriously doubt that it ever deals with windows handles however (this
is a constructer after all) but you never know. Hopefully someone can
clarify the situation. Anyway, thanks again.
 
C

Carl Daniel [VC++ MVP]

Michael Chambers said:
Thanks for the feedback. I'm the one who's authoring this form however and
the constructor will always perform simple initialization only (no window
handles are ever created). Since the form is originally created by the VS
form's designer however, I can't be sure what "InitializeComponent()" will
do. I seriously doubt that it ever deals with windows handles however
(this is a constructer after all) but you never know. Hopefully someone
can clarify the situation. Anyway, thanks again.

By the way, is this .NET 1.1 or 2.0?

-cd
 
M

Michael Chambers

I agree. I wouldn't bank on it either. Plus, if you're already
putting forth the effort to call ShowDialog on the UI thread then why
not instantiate the Form there too.

Originally I was going down this avenue but it soon became clear that it's
cleaner the way I'm proposing (assuming it's doable). I've rolled my own
message box (dialog) which has many properties and different constructor
variations (since the native "MessageBox()" function doesn't cut it for me).
If a thread wants to launch a dialog then it's much simpler for it to
construct the form on the fly and marshal it to the main GUI thread where
"ShowDialog()" will be called. One proxy function can then be written to
marshal the form's reference and this will handle every possible form
combination. The alternative is to write proxy functions for every form
combination which is hardly ideal. Besides, in theory it's the thread's job
to prepare the form and the main thread's job to display it ("theory" being
the operative word of course).
 
M

Michael Chambers

By the way, is this .NET 1.1 or 2.0?

2.0 but I might have to remedy that later.
 
B

Brian Gideon

Michael said:
Thanks for the feedback. I'm the one who's authoring this form however and
the constructor will always perform simple initialization only (no window
handles are ever created). Since the form is originally created by the VS
form's designer however, I can't be sure what "InitializeComponent()" will
do. I seriously doubt that it ever deals with windows handles however (this
is a constructer after all) but you never know. Hopefully someone can
clarify the situation. Anyway, thanks again.

Michael,

I have seen evidence in the past that something in the
InitializeComponent method was pumping messages. If that's true then
it's not out of the realm of possibility that a Form's thread affinity
is defined within its constructor. In reality I bet that's delayed
until Show or ShowDialog is called, but you never know.

Brian
 
M

Michael Chambers

Michael,
I have seen evidence in the past that something in the
InitializeComponent method was pumping messages. If that's true then
it's not out of the realm of possibility that a Form's thread affinity
is defined within its constructor. In reality I bet that's delayed
until Show or ShowDialog is called, but you never know.

Anything's possible but it seems so unlikely I find it hard to believe :) I
mean seriously, who at MSFT would allow that (and why)
 
M

Michael C

Michael Chambers said:
Anything's possible but it seems so unlikely I find it hard to believe :)
I mean seriously, who at MSFT would allow that (and why)

If you put a breakpoint on OnHandleCreated you can see it doesn't get fired
until Show or ShowDialog is called. You can probably do the same with by
overriding WndProc and looking for WM_CREATE.
 
B

Brian Gideon

Michael said:
Originally I was going down this avenue but it soon became clear that it's
cleaner the way I'm proposing (assuming it's doable). I've rolled my own
message box (dialog) which has many properties and different constructor
variations (since the native "MessageBox()" function doesn't cut it for me).
If a thread wants to launch a dialog then it's much simpler for it to
construct the form on the fly and marshal it to the main GUI thread where
"ShowDialog()" will be called. One proxy function can then be written to
marshal the form's reference and this will handle every possible form
combination. The alternative is to write proxy functions for every form
combination which is hardly ideal. Besides, in theory it's the thread's job
to prepare the form and the main thread's job to display it ("theory" being
the operative word of course).

Michael,

You said you were using 2.0. Would anonymous methods help you? This
is one area where I find anonymous methods particularly useful. You
wouldn't need any proxy functions. Here's an example.

private void ThreadMethod()
{
// Get parameters for the form to use.
object a = GetParameter1();
object b = GetParameter2();

// Use anonymous method to capture parameters and marshal a delegate.
mainForm.Invoke(delegate() {
YourForm form = new YourForm(a, b);
form.ShowDialog();
};

// Continue with further processing on this thread if necessary.
}

Brian
 
M

Michael Chambers

Anything's possible but it seems so unlikely I find it hard to believe :)
If you put a breakpoint on OnHandleCreated you can see it doesn't get
fired until Show or ShowDialog is called. You can probably do the same
with by overriding WndProc and looking for WM_CREATE.

Yes, but this is .NET and I can't make any assumptions about how things are
working under the hood (even though it's probably legit for now since much
of .NET is just a thin wrapper around the WinAPI).
 
M

Michael Chambers

Michael,
You said you were using 2.0. Would anonymous methods help you? This
is one area where I find anonymous methods particularly useful. You
wouldn't need any proxy functions. Here's an example.

private void ThreadMethod()
{
// Get parameters for the form to use.
object a = GetParameter1();
object b = GetParameter2();

// Use anonymous method to capture parameters and marshal a delegate.
mainForm.Invoke(delegate() {
YourForm form = new YourForm(a, b);
form.ShowDialog();
};

// Continue with further processing on this thread if necessary.
}

Thanks. I'll take a look at this though ideally I'd like to do it the way I
proposed (it does seem to be the most natural way). I'll see if I can get
someone at MSFT to confirm its legitimacy before exploring your idea and
others. Note that the method I proposed works in my environment (I tried it)
but that still doesn't mean it's safe of course. I really need [quasi]
official confirmation before I'll rely on it. Anyway, thanks again.
 
M

Michael C

Michael Chambers said:
Yes, but this is .NET and I can't make any assumptions about how things
are working under the hood (even though it's probably legit for now since
much of .NET is just a thin wrapper around the WinAPI).

If you can't make any such assumptions then why did you even post this
question? Aren't you asking if this is safe to do based on what's going on
under the hood?
 
M

Michael Chambers

Michael Chambers said:
If you can't make any such assumptions then why did you even post this
question? Aren't you asking if this is safe to do based on what's going on
under the hood?

I asked because I'm not sure if it's safe under .NET itself (which has
nothing to do with the WinAPI).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top