HastaLaVictoria Posted March 11, 2008 Posted March 11, 2008 G'day X.NET! I have a dilly of a pickle here, wondering if anyone can help a neighbourino out. </flanders> I have an application I'm building that uses asynchronous TCP connections to ferry data about between a server and multiple clients. I'm trying to implement a TreeView on my server UI form that will display all the connected clients' usernames. The problem I'm having is that I've written a method populateUserTree(), and called it from my receiveEvent() method, which is an AsyncCallback for BeginReceive. Whoops! Doesn't work, as the thread I'm in can't access the controls on the form. The error message hints at using Control.Invoke to achieve this, but the MSDN page on it isn't all that helpful. I took a stab in the dark and had my receiveEvent method call treeClients.Invoke(populateUserTree);, but that didn't work. The compile error was that a 'method group' could not be converted to a 'Delegate', so I presumed I got it horribly wrong and went on an Interwebs search for the answer. I found an MSDN article on delegates but it wasn't explaning what I wanted. Alas, nothing. So, in closing, can anyone provide an explanation, or example, of how to use Invoke to get a TreeView on a form to update, originating in another thread? The code I'm using to perform the actual updates to the TreeView treeClient is: treeClients.BeginUpdate(); treeClients.Nodes.Clear(); treeClients.Nodes.Add("Connected Clients"); foreach (ClientItem clientInfo in clientList) { treeClients.Nodes[0].Nodes.Add(clientInfo.strName); } treeClients.EndUpdate(); Thanks to anyone who can help. -Dru Quote
HastaLaVictoria Posted March 11, 2008 Author Posted March 11, 2008 (edited) Huzzah! Got it working. I found a good explanation of thread invocation. It was in fact one of the results on my Google for Control.Invoke, it just didn't have a title that screamed out at me. The trick, it seems, is to recursively invoke the method that's going to do it. My problem was that I wasn't specifying a delegate correctly. Here's the code I ended up with: private void populateUserTree() { if (treeClients.InvokeRequired) { treeClients.Invoke(new MethodInvoker(populateUserTree)); } else { treeClients.BeginUpdate(); treeClients.Nodes.Clear(); treeClients.Nodes.Add("Connected Clients"); foreach (ClientItem clientInfo in clientList) { treeClients.Nodes[0].Nodes.Add(clientInfo.strName); } treeClients.EndUpdate(); } } So when one of my threads calls populateUserTree, if (treeClients.InvokeRequired) checks to see if the current thread is able to play with the treeClients object. If it can't, it calls treeClients.Invoke(), passing a MethodInvoker object initialised using the same method that just called it, meaning the method is called again, one thread up in the ownership hierarchy (please correct me if that observation is wrong, or uses inadequate terminology - I don't want to mislead anyone by not using the right explanation). This process repeats until invocation is no longer required (i.e. we're in the right thread), dropping into the else block so that I can update the TreeView treeClients. -Dru Edited March 11, 2008 by HastaLaVictoria Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.