CodeGuru Forums -
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic Newsletters VB Forums Developer.com


Newest CodeGuru.com Articles:

  • Installing SQL Server 2008
  • Writing UDFs for Firebird Embedded SQL Server
  • [Updated] Shutdown Manager
  • Building Windows Azure Cloud Service Applications with Azure Storage and the Azure SDK

  • Search CodeGuru:
     



    Go Back   CodeGuru Forums > .NET Programming > C-Sharp Programming
    FAQ Members List Calendar Search Today's Posts Mark Forums Read

    C-Sharp Programming Post questions, answers, and comments about C#.

    Reply
     
    Thread Tools Search this Thread Rate Thread Display Modes
      #1    
    Old October 31st, 2009, 12:49 PM
    funkathustra funkathustra is offline
    Junior Member
     
    Join Date: Oct 2009
    Posts: 8
    funkathustra is an unknown quantity at this point (<10)
    Threading UI components

    I'm building a WPF photo viewing application, and trying to get a handle on threading. I've asked about this before in this forum -- and although everyone's reading suggestions have been good, I'm still having a hard time putting everything together.

    I have two listBoxes -- gallerySelector stores a the names of folders with which images are stored. PhotosListBox is populated with the photos in the directory specified by gallerySelector.

    The program is based on Microsoft's Photo Viewer WPF demo app (http://msdn.microsoft.com/en-us/library/ms771331.aspx)

    I want to make the gallerySelector more responsive (so you can arrow up and down through all the folders very quickly -- without having to wait for PhotosListBox to load alll the images), so I thought I'd try threading once again. But I'm failing miserably. Of course, I'm getting the following error message:

    Code:
    "The calling thread cannot access this object because a different thread owns it."

    Code:
    private void gallerySelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
            ThreadStart gallerySelectionThread = new ThreadStart(new ThreadStart(delegate()
                 {
                      this.Photos.Path = Environment.CurrentDirectory + "\\images\\" + gallerySelector.SelectedItem;
                      PhotosListBox.SelectedIndex = 0;
                 }
           ));
         Thread galleryThread = new Thread(gallerySelectionThread);
         galleryThread.SetApartmentState(ApartmentState.STA);
         galleryThread.Start();
     }
    where Photos is an ObservableCollection, described as:

    Code:
    public class PhotoCollection : ObservableCollection<Photo>
        {
            public PhotoCollection() { }
            public PhotoCollection(string path) : this(new DirectoryInfo(path)) { }
            public PhotoCollection(DirectoryInfo directory)
            {
                _directory = directory;
                Update();
            }
            public string Path
            {
                set
                {
                    _directory = new DirectoryInfo(value);
                    Update();
                }
                get { return _directory.FullName; }
            }
            public DirectoryInfo Directory
            {
                set
                {
                    _directory = value;
                    Update();
                }
                get { return _directory; }
            }
            private void Update()
            {
                this.Clear();
                try
                {
                    foreach (FileInfo f in _directory.GetFiles("*.jpg"))
                        Add(new Photo(f.FullName));
                }
                catch (DirectoryNotFoundException)
                {
                    System.Windows.MessageBox.Show("No Such Directory");
                }
            }
            DirectoryInfo _directory;
        }
    Would it work better to move the threading code into the ObservableClass definition? In addition, it would be great to populate the PhotosListBox item-by-item, so they would be inserted into the PhotosListBox as they are loaded and rendered.

    I'll be ecstatic if I can get this working -- I appreciate any help anyone can give me. Thanks!
    Reply With Quote
      #2    
    Old November 3rd, 2009, 06:24 PM
    funkathustra funkathustra is offline
    Junior Member
     
    Join Date: Oct 2009
    Posts: 8
    funkathustra is an unknown quantity at this point (<10)
    Re: Threading UI components

    Anyone?
    Reply With Quote
      #3    
    Old November 3rd, 2009, 06:52 PM
    BigEd781 BigEd781 is offline
    Member +
     
    Join Date: Jun 2008
    Posts: 1,005
    BigEd781 is a glorious beacon of light (400+)BigEd781 is a glorious beacon of light (400+)BigEd781 is a glorious beacon of light (400+)BigEd781 is a glorious beacon of light (400+)BigEd781 is a glorious beacon of light (400+)BigEd781 is a glorious beacon of light (400+)
    Re: Threading UI components

    http://hantou.blogspot.com/2009/04/c...perations.html

    You can also search this Google and this forum for "Cross thread exception" to find more info.
    Reply With Quote
      #4    
    Old November 3rd, 2009, 08:46 PM
    funkathustra funkathustra is offline
    Junior Member
     
    Join Date: Oct 2009
    Posts: 8
    funkathustra is an unknown quantity at this point (<10)
    Re: Threading UI components

    Thanks, that helped a bit -- I ended up finding this, which really got me going in the right direction. I modified my ObservablePhotoCollection class to this:

    Code:
            private void Update()
            {
                this.Clear();
                new Thread(new ParameterizedThreadStart(AddPhoto)).Start(_directory as object); 
            }
    
    
            void AddPhoto(object data)
            {
                foreach (FileInfo f in ((DirectoryInfo)data).GetFiles("*.jpg"))
                    try
                    {
                        Add(new Photo(f.FullName));
                    }
                    catch
                    {
                        MessageBox.Show("Cannot load image: " + f.FullName);
                    }
            }
    Everything works dandy, but if I switch between directories before the thread finishes executing, it will clear the list box, but the (not finished yet) thread continues to populate it with images from the LAST directory.

    So, I tried to declare the thread (instead of just new Thread()) so I could manipulate it later using Start() and Abort(), like this:

    Code:
            Thread AddPhotoThread = new Thread(new ParameterizedThreadStart(AddPhoto));  
    
            private void Update()
            {
                AddPhotoThread.Abort();
                Clear();
                AddPhotoThread.Start(_directory as object);
            }

    But I keep getting this error:

    Code:
    A field initializer cannot reference the non-static field, method, or property

    So, my next question: How do I setup my thread to start/stop later?
    Reply With Quote
      #5    
    Old November 3rd, 2009, 10:46 PM
    funkathustra funkathustra is offline
    Junior Member
     
    Join Date: Oct 2009
    Posts: 8
    funkathustra is an unknown quantity at this point (<10)
    Re: Threading UI components

    OK, after a bit more work, I've got this to work:

    Code:
            Thread AddPhotoThread; 
    
            private void Update()
            {
                try
                {
                    AddPhotoThread.Abort();
                }
                catch
                {
                }
                Clear();
                AddPhotoThread = new Thread(new ThreadStart(AddPhoto));
                AddPhotoThread.Start();
            }
    It seems to work, but it'll tank if I take out the try... catch... statement (since, on first run, the thread hasn't been set). I tried doing:

    Code:
    if(AddPhotoThread.IsAlive)
    {
     AddPhotoThread.Abort();
    }
    but that didn't work either. Any suggestions?
    Reply With Quote
      #6    
    Old November 4th, 2009, 12:08 AM
    dglienna's Avatar
    dglienna dglienna is offline
    ex MVP - Visual Basic
    Power Poster
     
    Join Date: Jan 2006
    Location: Chicago, IL
    Posts: 9,895
    dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)dglienna has a brilliant future (2000+)
    Re: Threading UI components

    It's not good to ABORT a thread, unless you have to. Just raise an event on the change event, and set a boolean in the loop. if threadRunning = True
    __________________
    David CodeGuru Article: Bound Controls are Evil-VB6
    101 Samples: VB & C# VS2008 Samples

    CodeGuru Reviewer
    2006 Dell CSP
    2006, 2007 & 2008 MVP Visual Basic
    If your question has been answered satisfactorily, and it has been helpful, then, please, Rate this Post!
    Reply With Quote
      #7    
    Old November 4th, 2009, 12:42 AM
    funkathustra funkathustra is offline
    Junior Member
     
    Join Date: Oct 2009
    Posts: 8
    funkathustra is an unknown quantity at this point (<10)
    Re: Threading UI components

    Quote:
    Originally Posted by dglienna View Post
    It's not good to ABORT a thread, unless you have to. Just raise an event on the change event, and set a boolean in the loop. if threadRunning = True
    *looks embarrassed* Yeah, I should have thought of that, shouldn't have I?

    Haha, how obvious is it that I'm an Electrical Engineering student who hasn't taken a programming class since Freshman year?

    Anyway, next question: if it's not a good idea to abort a thread, then how should I stop it? Can I send it a message to stop inserting images into the listbox if I switch directories? Looking at my code, what's the easiest way to implement that?

    Thanks for the help!
    Reply With Quote
    Reply

    Bookmarks

    Tags
    listbox, threading, wpf
    Go Back   CodeGuru Forums > .NET Programming > C-Sharp Programming


    Thread Tools Search this Thread
    Search this Thread:

    Advanced Search
    Display Modes Rate This Thread
    Rate This Thread:

    Posting Rules
    You may not post new threads
    You may not post replies
    You may not post attachments
    You may not edit your posts

    BB code is On
    Smilies are On
    [IMG] code is On
    HTML code is Off
    Forum Jump


    All times are GMT -5. The time now is 02:23 AM.



    Acceptable Use Policy

    internet.comMediabistrojusttechjobs.comGraphics.com

    WebMediaBrands Corporate Info


    Advertise | Newsletters | Feedback | Submit News

    Legal Notices | Licensing | Permissions | Privacy Policy


    Powered by vBulletin® Version 3.7.3
    Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
    Copyright WebMediaBrands Inc. 2002-2009