Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Threading and Windows Forms Question 2

Status
Not open for further replies.

ddvlad

Programmer
Mar 12, 2003
71
RO
I am faced with the following issue: I need to add all the files in a folder (chosen by the user) to a CheckedListBox (.Net 2.0). The user has the option to recurse subdirectories, which can naturally lead to a lot of files being added, which hangs the program.

To solve this I have created a separate class (potential design flaw?) that adds the files to the CheckedListBox. The method for doing so is being run in a separate thread, hence the problem: I get warned whiloe debugging that the control is being accessed by a thread other than the one it was created in. Is this a real problem? The program runs well outside debug mode and while the thread is running no other operations are being made on the CheckedListBox (except probably an occasional scroll by the user, which works fine). I have skimmed through a Microsoft example of safe cross-threading actions for Windows Forms, but it's beyond my level of comprehension for now.

Am I missing something? Is there a way to solve this while preserving responsiveness? You have probably realised by now that I am still learning, so I apologize if this is too basic. Thanks in advance.
 
I've run into this before, and once you understand it, it's pretty easy to do it right. You should google "thread affinity delegate c#" and that should get you started with what you need to do. Basically what it boils down to is that you can't/shouldn't update windows forms objects from any thread but the one that the windows form object was created on. In your case, you are adding items to a checkedlistbox on a thread separate from the one that the checkedlistbox was created on. So what happens is you need set up a delegate, and then use the invoke to call another method that does the actual updating. Other guys on here can explain it better, and provide code examples - but if you google that, it should get you started. Good luck!
 
I have tried immitating the example off msdn. It works, but I am actually experiencing a slower response from the user interface, because the main thread keeps getting invoked to update the checkedlistbox. The Google search yielded a Code-Project article which helped me understand, so thanks for that advice.

Because the aparently fast, convenient solution is not recommended (I mean my original approach) and Microsoft's solution is slow and unsuitable, I was thinking of creating an array of file names, then adding them all at once to the list. What would be the implications? Would it hog too much memory at times and be considered inefficient? Adding the files to the list afterwards would still take time, but less than actually searching for them on the spot, I presume.

Any other solutions or recommendations are welcome. Once again, thanks in advance.

--
People here are not only very knowledgeable, but also polite and helpful. My sincere congratulations to everyone.
 
Actually, using delegates between threads is also a problem. It seems MS does a similar thing with its system.window.forms.timer control but in actual fact, you should use the Invoke() method - where you invoke the method call on the original thread.

You will probably find that this has much better performance.
 
I agree - changing your delegate to accept an array (or ArrayList) of your updates would be a good way to go. That way you'd batch-up your updates so that the UI isn't stealing CPU cycles away from the code that's actually doing the work.

Unless you're running on a dual-core or dual-cpu machine, in which case that's less of a concern.

Chip H.


____________________________________________________________________
If you want to get the best response to a question, please read FAQ222-2244 first
 
OK, right now I have:

Code:
MainForm.ThreadSafeAddFile d = 
    new MainForm.ThreadSafeAddFile(_parentForm.AddFile);
foreach (string fileName in Directory.GetFiles(folderName))
{
    _parentForm.Invoke(d, new object[] { fileName });
}

It's pretty much based on what I have seen in the Microsoft example: ThreadSafeAddFile is a delegate void (string itemName). I would ideally add a "Please Wait" window that displayed a cancel button while adding. My question is: if the main thread displays a modal form, can it still update the checkedlistbox? If negative, how can I get around this? Another thread maybe? I wouldn't like to make any false assumptions before beginning to code that.

chiph said:
changing your delegate to accept an array (or ArrayList) of your updates would be a good way to go.

I am worried about the user panicking because the updates would be rather discontinuous. But that would probably be solved with a "Wait" form as I have described above. My main concern right now is if the main thread can update the form's control while displaying aa modal box.

Thanks again,
ddvlad
 
If the "Wait" form is being shown in a separate thread then yes, your form can update the control. Otherwise it will wait for the form to close before actually continuing.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top