InvokeRequired

S

Samuel White

Hi there,

I need to iterate all "TreeView" nodes on a worker thread. When doing so,
I'll call "InvokeRequired" and route all method/property calls through
"Invoke()" as required. However, for each "TreeNode" object I encounter in
the tree, must I also route method/property calls on this object through
"Invoke()" as well. I wouldn't think so since a "TreeNode" is not a control
in its own right so its methods/properties would presumably take care
calling "Invoke()" themselves if necessary (if they need to call the
"TreeView" methods for something). Is this correct? Thanks very much.
 
J

Jianwei Sun

Samuel said:
Hi there,

I need to iterate all "TreeView" nodes on a worker thread. When doing so,
I'll call "InvokeRequired" and route all method/property calls through
"Invoke()" as required. However, for each "TreeNode" object I encounter in
the tree, must I also route method/property calls on this object through
"Invoke()" as well. I wouldn't think so since a "TreeNode" is not a control
in its own right so its methods/properties would presumably take care
calling "Invoke()" themselves if necessary (if they need to call the
"TreeView" methods for something). Is this correct? Thanks very much.
I think you are correct. All the controls are running in the same UI
thread, so if you did the check on the TreeView control, there is no
need to call it again on the TreeNode again..

HTH.
J.W.
 
B

Brian Gideon

Samuel,

You'll need to limit access to a TreeNode as you would any control.
That rule applies to almost everything in the System.Windows.Form
namespace.

Brian
 
J

Jianwei Sun

Brian said:
Samuel,

You'll need to limit access to a TreeNode as you would any control.
That rule applies to almost everything in the System.Windows.Form
namespace.

Brian

But if he already checked the TreeView Control, does he need to check
each TreeNode again. I assume after he checked TreeView control, the
thread should already be marshaled properly to the UI thread.
 
S

Samuel White

But if he already checked the TreeView Control, does he need to check each
TreeNode again. I assume after he checked TreeView control, the thread
should already be marshaled properly to the UI thread.

Thanks for both your feedback. Keep in mind however that a "TreeNode" isn't
a control itself. My thinking is that I simply need to call "TreeView.Nodes"
via "Invoke()" which then returns a "TreeNodeCollection" (a collection of
"TreeNode" objects). Once I have this collection however, shouldn't I be
free to call into it directly since it's not a control itself? If it needs
to talk to the "TreeView" for some reason then shouldn't that be its own
responsibility? BTW, it does work problem-free this way but it's still no
guarantee I'm doing it correctly (and could break at some later point).
 
J

Jianwei Sun

Samuel said:
Thanks for both your feedback. Keep in mind however that a "TreeNode" isn't
a control itself. My thinking is that I simply need to call "TreeView.Nodes"
via "Invoke()" which then returns a "TreeNodeCollection" (a collection of
"TreeNode" objects). Once I have this collection however, shouldn't I be
free to call into it directly since it's not a control itself? If it needs
to talk to the "TreeView" for some reason then shouldn't that be its own
responsibility? BTW, it does work problem-free this way but it's still no
guarantee I'm doing it correctly (and could break at some later point).
I believe you are doing correctly as long as you make sure you check
InvokeRquired when you call the TreeView control.
 
B

Brian Gideon

Jianwei said:
But if he already checked the TreeView Control, does he need to check
each TreeNode again. I assume after he checked TreeView control, the
thread should already be marshaled properly to the UI thread.

No that's fine. The bottom line is that a TreeNode can only be
accessed from the UI thread and shouldn't be seen as an exception to
the rule just because it doesn't subclass Control.
 
L

Lucian Wischik

Samuel White said:
I need to iterate all "TreeView" nodes on a worker thread.

(in addition to the other more useful replies in this thread...)

Do you really need to do this? It sounds like you might be storing
your data in UI objects, when they'd be better of being stored in your
own UI-independent objects that you make yourself. That way the worker
threads won't need to interact with the UI.

If you're trying to get two threads to interact with the UI to gain
performance, it won't really gain performance. It'd probably cause
slowdown due to all the synchronization.
 
B

Brian Gideon

Samuel said:
Thanks for both your feedback. Keep in mind however that a "TreeNode" isn't
a control itself. My thinking is that I simply need to call "TreeView.Nodes"
via "Invoke()" which then returns a "TreeNodeCollection" (a collection of
"TreeNode" objects).

Anything relating to a TreeView object can only be accessed from the UI
thread. That includes the TreeNodeCollection even though it doesn't
subclass Control.
Once I have this collection however, shouldn't I be
free to call into it directly since it's not a control itself?

No. You cannot touch it from a worker thread because it may be bound
to the TreeView.
If it needs
to talk to the "TreeView" for some reason then shouldn't that be its own
responsibility?

No. It simply won't do that.
BTW, it does work problem-free this way but it's still no
guarantee I'm doing it correctly (and could break at some later point).

Like you said, it may appear to work, but that doesn't mean it's
correct.
 
S

Samuel White

No that's fine. The bottom line is that a TreeNode can only be
accessed from the UI thread and shouldn't be seen as an exception to
the rule just because it doesn't subclass Control.

Thanks but can you clarify. The pattern I'm hoping to use is this:

1) On the worker thread, use "Invoke()" to call "TreeView.Nodes" which
returns the "TreeNode" collection
2) Access the collection returned in 1) above directly from the worker
thread itself (no need to call "Invoke" again since the collection isn't a
control)

Will this work or is item 2 incorrect (i.e., does "Invoke" still need to be
called and if so why?)
 
S

Samuel White

Samuel White said:
(in addition to the other more useful replies in this thread...)

Do you really need to do this? It sounds like you might be storing
your data in UI objects, when they'd be better of being stored in your
own UI-independent objects that you make yourself. That way the worker
threads won't need to interact with the UI.

If you're trying to get two threads to interact with the UI to gain
performance, it won't really gain performance. It'd probably cause
slowdown due to all the synchronization.

The worker thread is kicked off via a button handler on a dialog. I need to
iterate a "TreeView" on the dialog from this thread. I considered copying
the tree nodes to another (binary-tree) collection first but don't see any
tree-based collection available (unless you can recommend one - it
effectively has to provide the same parent/child relationships as a
"TreeView"). I don't want to bother writing my own for this purpose. If I
have to repeatedly call into the nodes collection on the tree's thread I
will but I wanted to avoid this obviously. I think any degradation in
performance by doing so will be minimal however since the time required to
iterate a few hundred or even a few thousand nodes should be negligible
(especially when compared to the other processing required on my worker
thread). Thanks for your help.
 
J

Jianwei Sun

Samuel said:
Thanks but can you clarify. The pattern I'm hoping to use is this:

1) On the worker thread, use "Invoke()" to call "TreeView.Nodes" which
returns the "TreeNode" collection
2) Access the collection returned in 1) above directly from the worker
thread itself (no need to call "Invoke" again since the collection isn't a
control)

Will this work or is item 2 incorrect (i.e., does "Invoke" still need to be
called and if so why?)

If you want to call the TreeNode collection which is on the UI thread
from the worker thread, you still need to call "Invoke" to marshal the
call to the UI thread again.
 
B

Brian Gideon

Samuel said:
1) On the worker thread, use "Invoke()" to call "TreeView.Nodes" which
returns the "TreeNode" collection
2) Access the collection returned in 1) above directly from the worker
thread itself (no need to call "Invoke" again since the collection isn't a
control)

Will this work or is item 2 incorrect (i.e., does "Invoke" still need to be
called and if so why?)

Item 2 is incorrect. Invoke still needs to be called. The reason is
because the collection is obtained from the control and could be bound
to it. In fact, in the case of TreeView and TreeNodeCollection that's
precisely the setup. Calling members on TreeNodeCollection in turn
calls members on TreeView. The same true for TreeNode. This can be
verified by looking at the IL code.

It may be working for you, but that's either by accident or
coincidence. If you continue to do it then it may eventually fail.
 
S

Samuel White

1) On the worker thread, use "Invoke()" to call "TreeView.Nodes" which
Item 2 is incorrect. Invoke still needs to be called. The reason is
because the collection is obtained from the control and could be bound
to it. In fact, in the case of TreeView and TreeNodeCollection that's
precisely the setup. Calling members on TreeNodeCollection in turn
calls members on TreeView. The same true for TreeNode. This can be
verified by looking at the IL code.

It may be working for you, but that's either by accident or
coincidence. If you continue to do it then it may eventually fail.

Ok, thanks for yours and everyone else's help. BTW, do you know of any
tree-based collection class I can use instead. I'll copy my "TreeView" into
it on the main GUI thread and hand it to my worker thread. Thanks again.
 
B

Brian Gideon

Samuel said:
Ok, thanks for yours and everyone else's help. BTW, do you know of any
tree-based collection class I can use instead. I'll copy my "TreeView" into
it on the main GUI thread and hand it to my worker thread. Thanks again.

I'm not aware of a collection that would be suitable. You'll probably
have to write your own. But, you're on the right track now.
 
S

Samuel White

I'm not aware of a collection that would be suitable. You'll probably
have to write your own. But, you're on the right track now.

Yes, thanks to you and the others (appreciated).
 

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