Suppose I were to take a treeview and add some nodes, in a BFS manner, but also in a thread safe way.
treeView.Invoke((MethodInvoker)delegate{treeView.Nodes.Add(someNode);});
Later I'd like to add a node to one of the nodes added to the treeView (as my depth increases by one). How would I know that the treeView had had all of it's depth one nodes added before adding the second layer of nodes. By the way, the information at the second level depends on the first level. All of this is just 开发者_Python百科an example of what I need, but it is secondary to the real question at hand.
Maybe somebody expands a node and I'd like to add nodes to that node first... in which case I'd like to interrupt the invocation list of the treeView, and start adding nodes at the node that was expanded.
How can I do either of these tasks?
I suppose I could add nodes in a depth first fashion, but I don't want to. Is there a better way?
I really hate the idea that a message/delegate queue is forming under the hood and I have no control over it.
How the delegates are queued under the hood
The actual delegates are stored in a queue in a private field named threadCallbackList on the control or closest parent control who's handle has already been created. The data structure is just a System.Collections.Queue
.
Knowing that the TreeView had had all of it's depth-one nodes added
If you want to communicate to the main thread that a node has had all of it's children populated you can store something (an enum) in the node's Tag
property to indicate that.
If you're thinking you need to communicate back to the background thread that the delegate that adds the final node to a level of the treeview has run, you don't. The delegates you submit using BeginInvoke
and Invoke
will execute in order.
Interrupting the execution of BeginInvoke
d delegates
There is no way you could interrupt the execution of queued delegates on the UI thread from a click on a control on the same thread. The delegate execution is just like any other part of your program. It's a loop that dequeues each of the delegates and executes them. You're UI thread will be executing those delegates so it can't also execute the click event handler that would try to interrupt the execution of the queued delegates. Even if you could figure out how to use reflection to mess with the queued delegates you couldn't possibly do it at the same time that other code is running in the same thread.
Possible solution
It sounds like you are just worried about swamping your UI thread. If that's the case you could throttle your background thread by calling Invoke
instead of BeginInvoke
every Nth call. This will cause your background worker thread to wait until the queue is flushed (at least up to the delegate passed in that call). That way you'd never have more than N queued delegates at a time. If you went that route you could just Invoke
everytime and use AddRange(someNodes)
instead of Add(someNode)
.
精彩评论