Winforms and threads

  • Thread starter Thread starter J.Marsch
  • Start date Start date
J

J.Marsch

I know that the controls on a Winform are not thread safe, and that you want
to do all of your UI updates on a single thread -- generally the main
thread.

Now, 2 questions:
1. Does the one thread that you can use to update controls have to be the
thread that you were on when you instanced the form?

2. Can 2 forms in the same application have affinity for different threads,
or do you want all of the forms in an application to be created on the main
thread?

Why I'm asking:

I'm working on a module that will place an item in system tray. The code
associated with the tray item will use a secondary thread to listen for
system events, and based on some of the events, it might have to launch a
form. Do I need to work in some logic to make sure that the form launch
code is always executed by the main thread?
 
Hi J.Marsch,
I know that the controls on a Winform are not thread safe, and that you want
to do all of your UI updates on a single thread -- generally the main
thread.
Now, 2 questions:
1. Does the one thread that you can use to update controls have to be the
thread that you were on when you instanced the form?

The thread which has created the control (this thread owns the underlying
windows' control handle) can update the control. This is Windows requirement
rather than Windows Form's one.
2. Can 2 forms in the same application have affinity for different threads,
or do you want all of the forms in an application to be created on the main
thread?
You may have many UI threads any of them may has created bunch of forms and
controls. The rule for the version of .NET running on windows platform is:
You have to update a control only from the thread that owns the control's
HWND (this is thread created the control)
Why I'm asking:

I'm working on a module that will place an item in system tray. The code
associated with the tray item will use a secondary thread to listen for
system events, and based on some of the events, it might have to launch a
form. Do I need to work in some logic to make sure that the form launch
code is always executed by the main thread?
From any thread you can call Control.Invoke to execute a method in the UI
thread created the control or form and let this method udate the controls.
Usually main form's Invoke is used.

HTH
B\rgds
100
 
Hi,

I know that the controls on a Winform are not thread safe, and that you want
to do all of your UI updates on a single thread -- generally the main
thread.

Now, 2 questions:
1. Does the one thread that you can use to update controls have to be the
thread that you were on when you instanced the form?

2. Can 2 forms in the same application have affinity for different threads,
or do you want all of the forms in an application to be created on the main
thread?

Why I'm asking:

I'm working on a module that will place an item in system tray. The code
associated with the tray item will use a secondary thread to listen for
system events, and based on some of the events, it might have to launch a
form. Do I need to work in some logic to make sure that the form launch
code is always executed by the main thread?

Every form has Form.InvokeRequired, which you have to inspect to see if
you should need Invoke.
Maybe this is not good solution, but in my form (I want to change a
label field) I use this additions:

private delegate void ChangeActionTextDelegate(string newtext);

public void SetActionText(string txt)
{
if (this.InvokeRequired)
this.Invoke(new ChangeActionTextDelegate(
this.ChangeActionText),new object[] {txt});

else
this.ChangeActionText(txt);
}

private void ChangeActionText(string newtext)
{
this.lAction.Text = newtext;
this.lAction.Refresh();
}

So, whenever you want to change the text, doesn't matter from which
thread, you call the public method SetActionText, and it makes sure that
the call is forwarded to the form thread if necessary.

Also, it seems possible the public method to look like:

public void SetActionText (string txt)
{
if (this.InvokeRequired)
this.Invoke(new ChangeActionTextDelegate(
this.SetActionText), new object[] {txt});

else
{
this.lAction.Text = newtext;
this.lAction.Refresh();
}
}

I.e, you may skip the private method, and to make the form thread to
invoke the same public method.

I just don't like this, becausee I'm not so sure that it is safe at all
(I tried, it worked), and because in the first approach the things are
more readable.

So, you can use similar things for every form control, which you have to
change.

!!!CAUTION!!!

I do not know why, but this approach does not work with properties. If
you put the if statement in a public property, and not in a method, it
hangs the same way, as if you are trying to change a control directly.

Hope that helps
Sunny
 
Hi,

In winform, controls in Windows Forms are bound to a specific thread and
are not thread safe.
There are four methods on a control that are safe to call from any thread:
Invoke, BeginInvoke, EndInvoke and CreateGraphics. For all other method
calls, you should use one of these invoke methods when calling from a
different thread.

The sample below tells you how to manipulate multithreading winform
controls:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconDevelopingMultithreadedWindowsFormsControl.asp

Hope this helps,
Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Thank you all for your input, but there's a fine point here that I'm trying
to close in on. We are on the same page regarding Invoke and that the
"owning" thread must fire events on the control, and I agree that this is a
Windows issue, not winforms.

What I'm lost on:
What would be best practice for instancing a form? In my example, a
background thread will possibly need to throw up a form in response to a
system event. When that happens, from a best-practice point of view, am I
ok just instancing a form on the spot, or am I better off creating a pattern
that will cause the form to be created on the application's Main thread?
 
Do what works for you. Why Must you follow everybody else when you're
solution is for you.

If I told you to shove yer hand in the oven , would you? Or cut on yer
gonads?

J.Marsch said:
Thank you all for your input, but there's a fine point here that I'm trying
to close in on. We are on the same page regarding Invoke and that the
"owning" thread must fire events on the control, and I agree that this is a
Windows issue, not winforms.

What I'm lost on:
What would be best practice for instancing a form? In my example, a
background thread will possibly need to throw up a form in response to a
system event. When that happens, from a best-practice point of view, am I
ok just instancing a form on the spot, or am I better off creating a pattern
that will cause the form to be created on the application's Main thread?

"Jeffrey Tan[MSFT]" said:
Hi,

In winform, controls in Windows Forms are bound to a specific thread and
are not thread safe.
There are four methods on a control that are safe to call from any thread:
Invoke, BeginInvoke, EndInvoke and CreateGraphics. For all other method
calls, you should use one of these invoke methods when calling from a
different thread.

The sample below tells you how to manipulate multithreading winform
controls:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconDevelopingMultithreadedWindowsFormsControl.asp

Hope this helps,
Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Well, with all due respect (though you've shown me none). What works for me
may not work for Windows. If I'm about to make a design decision that will
affect the architecture of a UI layer that will be used in multiple
applications, and as the basis for the design of hundreds of forms, don't
you sort of think that it would be a good idea to make sure that the
threading model is compatible with the Windows UI layer???

That's called called due dilligence and common sense, Alvin.

If you don't have anything useful to add to this conversation, why don't
you just crawl back under whatever rock you came out from under.

Alvin Bruney said:
Do what works for you. Why Must you follow everybody else when you're
solution is for you.

If I told you to shove yer hand in the oven , would you? Or cut on yer
gonads?

J.Marsch said:
Thank you all for your input, but there's a fine point here that I'm trying
to close in on. We are on the same page regarding Invoke and that the
"owning" thread must fire events on the control, and I agree that this
is
a
Windows issue, not winforms.

What I'm lost on:
What would be best practice for instancing a form? In my example, a
background thread will possibly need to throw up a form in response to a
system event. When that happens, from a best-practice point of view, am I
ok just instancing a form on the spot, or am I better off creating a pattern
that will cause the form to be created on the application's Main thread?

"Jeffrey Tan[MSFT]" said:
Hi,

In winform, controls in Windows Forms are bound to a specific thread and
are not thread safe.
There are four methods on a control that are safe to call from any thread:
Invoke, BeginInvoke, EndInvoke and CreateGraphics. For all other method
calls, you should use one of these invoke methods when calling from a
different thread.

The sample below tells you how to manipulate multithreading winform
controls:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
 
Gotcha. That's exactly what I needed to know. Thank you very much.

Regards.

-- Jeremy


100 said:
Hi J.Marsch,
What I'm lost on:
What would be best practice for instancing a form? In my example, a
background thread will possibly need to throw up a form in response to a
system event. When that happens, from a best-practice point of view, am I
ok just instancing a form on the spot, or am I better off creating a pattern
that will cause the form to be created on the application's Main thread?

You don't have options in this case. if you create the form in the worker
thread it won't receive any win messages and will stay frozen. If you want
your form to do something you have to pump messages (Application.Run or
Application.DoEvents) in your worker thread, which is not what you want to
do in your worker thread I believe.
So the only option is to let the main UI thread throw up the form. Use
Control.Invoke to switch to the main UI thread, etc.

HTH
B\rgds
100
"Jeffrey Tan[MSFT]" said:
Hi,

In winform, controls in Windows Forms are bound to a specific thread and
are not thread safe.
There are four methods on a control that are safe to call from any thread:
Invoke, BeginInvoke, EndInvoke and CreateGraphics. For all other method
calls, you should use one of these invoke methods when calling from a
different thread.

The sample below tells you how to manipulate multithreading winform
controls:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
 
Hi J.Marsch,
What I'm lost on:
What would be best practice for instancing a form? In my example, a
background thread will possibly need to throw up a form in response to a
system event. When that happens, from a best-practice point of view, am I
ok just instancing a form on the spot, or am I better off creating a pattern
that will cause the form to be created on the application's Main thread?

You don't have options in this case. if you create the form in the worker
thread it won't receive any win messages and will stay frozen. If you want
your form to do something you have to pump messages (Application.Run or
Application.DoEvents) in your worker thread, which is not what you want to
do in your worker thread I believe.
So the only option is to let the main UI thread throw up the form. Use
Control.Invoke to switch to the main UI thread, etc.

HTH
B\rgds
100
"Jeffrey Tan[MSFT]" said:
Hi,

In winform, controls in Windows Forms are bound to a specific thread and
are not thread safe.
There are four methods on a control that are safe to call from any thread:
Invoke, BeginInvoke, EndInvoke and CreateGraphics. For all other method
calls, you should use one of these invoke methods when calling from a
different thread.

The sample below tells you how to manipulate multithreading winform
controls:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconDevelopingMultithreadedWindowsFormsControl.asp

Hope this helps,
Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Its called MSDN, go read it.


J.Marsch said:
Well, with all due respect (though you've shown me none). What works for me
may not work for Windows. If I'm about to make a design decision that will
affect the architecture of a UI layer that will be used in multiple
applications, and as the basis for the design of hundreds of forms, don't
you sort of think that it would be a good idea to make sure that the
threading model is compatible with the Windows UI layer???

That's called called due dilligence and common sense, Alvin.

If you don't have anything useful to add to this conversation, why don't
you just crawl back under whatever rock you came out from under.

am
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
 
Hmm.

I think I'm finished here, you've clearly hit a point where you cannot
logically argue, so you're throwing out a few one-liners.

I can't help but to point out that your initial argument was "just do what
works for you", and now you are attempting to back that up by suggesting
that I go read about what other people are doing.
Hmm.

But beyond that, I would love to hear your explanation of exactly what you
think these newsgroups are for.

Personally, I use them as a resource for seeking answers to general
questions, so that I can tune my research, and as airing platform so that I
can get reality checks on technical and design decisions, and as an
opportunity to poll the experience of other professionals when I feel it
appropriate.

I also try to repay the community by providing constructive, helpful
responses when I encounter someone with a problem that I am familiar with.
Oh, and since I do pay for MSDN Universal, which includes newsgroup support,
I feel completely entitled to post a question when one arises.
 
Back
Top