locked
Multi-Threading and Windows Forms RRS feed

  • Question

  • Current situation:

    - Windows Forms
    - Connect via HttpWebRequest/HttpWebResponse to retrieve an XML file, via a web service, with file listings with folders (example of the XML file is below):
    (No Sub Folders - Animals.xml):
    <response>
    <message success="1"></message>
    <files name="animals" count="125">
    <file>Bird 9.png</file>
    <file>Otter.png</file>
    <file>Dog 6.png</file>
    <file>Duck 2.png</file>
    <file>Pig 2.png</file>
    ....
    </files>
    </response>

    (With Sub Folder - Seasonal.xml):
    <response>
    <message success="1"></message>
    <files name="seasonal" count="4">
    <folder name="summer" count="50"></folder>
    <folder name="autumn" count="20"></folder>
    <folder name="winter" count="18"></folder>
    <folder name="spring" count="33">
    <file>Flower 2.png</file>
    <file>Tree 3.png</file>
    <file>Butterfly 2.png</file>
    <file>Tree 1.png</file>
    <file>Flower 10.png</file>
    ...
    </folder>
    </files>
    </response>

    - Once I load the XML file, I use the XMLNodeList to build a list (in the case of the Sub Folders, I would get Summer, Autumn, Winter and Spring), and use those titles to build a TabPage object. (The Code Below shows how I go about it, and this code is placed in the Form_Load event).
               
                clipArt = new Clip_Art("seasonal");
                XmlNodeList folderList = clipArt.GetFolders();
                tabControl1.TabPages.Clear();
                Thread t;
                foreach (XmlNode folder in folderList)
                {
                    Console.WriteLine(folder.Attributes[0].InnerText);
                    //Create the tabs
                    TabPage page = AddTabPage(tabControl1, folder.Attributes[0].InnerText);
                    //DO THE THREAD HERE!! The images take the longest because it has to connect to the web server.
                    lock (stateLock)
                    {
                        _page = page;
                        _folder = folder;
                    }
                
                    t = new Thread(new ThreadStart(AddImages));
                    t.IsBackground = true;
                    t.Start();
                }
    - The class Clip_Art handles the communication to my web service. I don't believe I need to show this as my threading is the issue
    - Once we know what folders we need, the AddImages method adds the Image type images to a listview (each Image being a ListViewItem type).

    Problem:

    The XML File that I retrieve works fine for those that dont' have a sub folder (the XML I showed at the top [Animals.xml]). When it comes to the Seasonal.xml file, some tabs don't behave the same as the non-sub folder XML file. For example: Spring wouldn't load any images at all, Autumn would duplicate its images twice, Winter would work fine as well as Spring.

    I have a feeling it's because of the way I have my threading done. When I do the debugging, it seems to skip over Spring entirely. Any advice would be appreciated. If you want to see the AddImages method, it's a big one, and I'm personally very sub-concious of that code (haha).

    If you need more code to work with, I'll give you what I can.
    Thursday, February 18, 2010 7:42 PM

Answers

  • You cannot, under any circumstances, touch a UI element on any thread other than the thread that created it.  For WinForms this includes using any member of any class that derives from Control.  A few exceptions exist such as BeginInvoke, EndInvoke, Invoke and InvokeRequired.  All others will cause an eventual exception in your app at some point that is completely random.  In the debugger the MDA should kick in and let you know you've messed up.

    What you should do instead is perform your WS call on a secondary thread and then do the UI update on the UI thread.  The BackgroundWorker component was added to v2 to solve this very problem and is generally the best way to go rather than creating your own thread.  BWC supports progress notification, cancellation and completion events.  These events are raised on the UI thread so you don't have to do any marshaling.  A full discussion is beyond the scope of this post so refer to MSDN and the many articles on it.  Here's one I wrote a while back: http://p3net.mvps.org/Topics/WinForms/BackgroundWorker.aspx

    Michael Taylor - 2/18/2010
    http://msmvps.com/blogs/p3net
    • Marked as answer by AlAccess Friday, February 19, 2010 12:18 AM
    Thursday, February 18, 2010 9:06 PM

All replies

  • You cannot, under any circumstances, touch a UI element on any thread other than the thread that created it.  For WinForms this includes using any member of any class that derives from Control.  A few exceptions exist such as BeginInvoke, EndInvoke, Invoke and InvokeRequired.  All others will cause an eventual exception in your app at some point that is completely random.  In the debugger the MDA should kick in and let you know you've messed up.

    What you should do instead is perform your WS call on a secondary thread and then do the UI update on the UI thread.  The BackgroundWorker component was added to v2 to solve this very problem and is generally the best way to go rather than creating your own thread.  BWC supports progress notification, cancellation and completion events.  These events are raised on the UI thread so you don't have to do any marshaling.  A full discussion is beyond the scope of this post so refer to MSDN and the many articles on it.  Here's one I wrote a while back: http://p3net.mvps.org/Topics/WinForms/BackgroundWorker.aspx

    Michael Taylor - 2/18/2010
    http://msmvps.com/blogs/p3net
    • Marked as answer by AlAccess Friday, February 19, 2010 12:18 AM
    Thursday, February 18, 2010 9:06 PM
  • is this xml Valid?

    <folder name="summer" count="50"></folder>
    <folder name="autumn" count="20"></folder>
    <folder name="winter" count="18"></folder>
    <folder name="spring" count="33"> where are u closing it?

    Thanks Mike --------Please mark as answer if it is useful----------
    Thursday, February 18, 2010 9:08 PM