Results 1 to 19 of 19
  1. #1
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Question Fire Event When Thread is Complete

    Hello, world!

    The app I'm working on loads some thumbnails and displays them. I already have it working, but I want to load the thumbnails in a separate thread. After plenty of googling, I figured out how to create a new thread, pass it the information it needs, and run it. The problem is, I don't know how to get the image data back when it's finished. Waiting for it is out of the question, as that would defeat the purpose of the thread :rolleyes: . The best solution I can come up with is to get it to call a method when it's finished that displays the thumbnails. My efforts to Google it were futile.

    Thanks in advance!

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    You will likely need to provide more details. What kind of GUI library are you using? Swing? If so are you using a SwingListener for the background thread? If so, there are ways of detecting when such a beast has finished either by code in its done method or by attaching a property change listener to this thread and listening to its state bound property.

  3. #3
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Default

    Thanks for the reply. The toolkit I'm using is SWT. The GUI is in the main thread, and any computation/logic will be running in the background. For the background thread right now, I'm using a class implementing Runnable with a run() method.

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    Myself I don't use SWT, but I'm guessing that there'd be a way to use a bounded property and a PropertyChangeListener here.

  5. #5
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Default Can objects be passed between threads?

    Okay, I'll look into PropertyChangeListener. I haven't yet learned about Java Beans; I suppose this is a good opportunity :)

    Alternatively, is there a way to pass a message from a child thread? I Googled that too, but to no avail.
    Last edited by Jonah Bron; 10-26-2010 at 05:32 AM.

  6. #6
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    Look up the observer design pattern.

    And for more on Beans and bound properties and how to add property change support to your class, please have a look here: JavaBeans: Properties
    Last edited by Fubarable; 10-26-2010 at 03:49 PM.

  7. #7
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Default

    Okay, thanks a lot. The Java Observer interface should do what I need. I'm still surprised that something like this isn't a little more simple.

    Thanks for the help. (if anyone has more, please say it)

  8. #8
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Default

    Okay, I implemented the Observer pattern. The problem is, for some reason the Observer is being run in the child thread, instead of the main thread. I get a "Invalid thread access" exception. Here's the layout:

    Java Code:
    Main class in main thread
    Subject (Observable) in second thread
    Observer

    Main class:
    Java Code:
    PreviewObserver observer = new PreviewObserver();
    observer.setWidget(swt_widget); // this is an array
    
    PreviewSubject subject = new PreviewSubject();
    subject.addObserver(observer);
    
    Thread thread = new Thread(subject);
    thread.start();

    The observer receives the update from the subject, and tries to put the thumbnail into the widget provided through setWidget. That's where I get the error. I modeled after the example on the Wikipedia page.

    How do I get the observer into the main thread, or how do I access the widget from the child thread?
    Last edited by Jonah Bron; 10-26-2010 at 10:58 PM. Reason: Formatting for readability

  9. #9
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    Please check out the 3rd link in my signature links on how to create an SSCCE (or click here: SSCCE), and then I suggest you create one and post it.

    Luck!

  10. #10
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Default

    Okay, here it is. Strange though, this works. I think since the GUI is continuously running, there is some sort of lock on the widgets or something. I'll re-do it with a widget.

    SscceeTest.java:
    Java Code:
    import java.awt.Point;
    
    public class SscceTest
    {
    	public static void main(String args[])
    	{
    		System.out.println("The main class is working in thread: " + Thread.currentThread().getName());
    		
    		Point pt = new Point(1, 1);
    		
    		changePoint(pt);
    	}
    	
    	public static void changePoint(Point pt)
    	{
    		SscceObservable subject = new SscceObservable();
    		
    		SscceObserver observer = new SscceObserver();
    		observer.setPoint(pt);
    		
    		subject.addObserver(observer);
    		
    		Thread thread = new Thread(subject);
    		thread.start();
    	}
    }

    SscceeObserver.java:
    Java Code:
    import java.awt.Point;
    import java.util.Observable;
    import java.util.Observer;
    
    public class SscceObserver implements Observer
    {
    	private Point point;
    	
    	public void setPoint(Point pt)
    	{
    		point = pt;
    	}
    	
    	public void update(Observable subject, Object updateArg) {
    		Integer update[] = (Integer[]) updateArg;
    		point.x = update[0];
    		point.y = update[1];
    		System.out.println("Update recieved");
    		System.out.println("The observer is working in thread: " + Thread.currentThread().getName());
    	}
    }

    SscceObservable.java:
    Java Code:
    import java.util.Observable;
    
    public class SscceObservable extends Observable implements Runnable
    {
    	public void run()
    	{
    		Integer pos[] = new Integer[2];
    		pos[0] = 20;
    		pos[1] = 30;
    		setChanged();
    		System.out.println("The subject is working in thread: " + Thread.currentThread().getName());
    		notifyObservers(pos);
    	}
    }

    Even though it works, it does prove that the observer is working in Thread-0, instead of main. The whole idea behind my implementing this pattern was to keep it in the right thread, I think :(

    Interestingly enough, I already read all of the links in you signature :D

  11. #11
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Default

    Okay, here it is. This fails, with the same error as before: "Invalid thread access".

    SscceTest.java:
    Java Code:
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Label;
    import org.eclipse.swt.widgets.Shell;
    
    public class SscceTest
    {
    	public static void main(String args[])
    	{
    		// Create widgets
    		Display display = new Display();
    		
    		Shell shell = new Shell(display, SWT.DIALOG_TRIM | SWT.MIN);
    		shell.setSize(340, 348);
    		shell.setLocation(450, 300);
    		shell.setText("Window");
    		
    		Label msg = new Label(shell, SWT.LEFT);
    		msg.setLocation(12, 12);
    		msg.setSize(310, 30);
    		msg.setText("This text has not been changed");
    		
    		System.out.println("The main class is running in thread: " + Thread.currentThread().getName());
    		
    		//Create Observable instance
    		SscceObservable subject = new SscceObservable();
    		
    		//Create observer and pass the widget
    		SscceObserver observer = new SscceObserver();
    		observer.setLabel(msg);
    		
    		//Add observer to observable
    		subject.addObserver(observer);
    		
    		//Start
    		Thread thread = new Thread(subject);
    		thread.start();
    		
    		//Just more SWT stuff
    		shell.open();
    		while (!shell.isDisposed()) {
    			if (!display.readAndDispatch()) {
    				display.sleep();
    			}
    		}
    	}
    }

    SscceObserver.java
    Java Code:
    import java.util.Observable;
    import java.util.Observer;
    import org.eclipse.swt.widgets.Label;
    
    public class SscceObserver implements Observer {
    	private Label message;
    	
    	public void setLabel(Label msg) {
    		message = msg;
    	}
    	
    	public void update(Observable subject, Object updateArg) {
    		String msg = (String) updateArg;
    		message.setText(msg);
    		System.out.println("Update recieved");
    		System.out.println("The observer is working in thread: " + Thread.currentThread().getName());
    	}
    }

    SscceObservable.java
    Java Code:
    import java.util.Observable;
    
    public class SscceObservable extends Observable implements Runnable {
    	public void run() {
    		try {
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    		}
    		System.out.println("The subject is working in thread: " + Thread.currentThread().getName());
    		setChanged();
    		notifyObservers("This text has been changed");
    	}
    }
    This code embodies the problem I'm having in the simplest form I could make it. Thanks.

  12. #12
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    Here is my attempt to do something similar with PropertyChangeListener support:

    Java Code:
    import java.awt.Point;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.beans.PropertyChangeSupport;
    import java.util.ArrayList;
    import java.util.List;
    
    public class SscceTest2 {
       public static void main(String[] args) {
          System.out.println("The main class is working in thread: " + 
                   Thread.currentThread().getName());
    
          final List<MyPoint> points = new ArrayList<MyPoint>();
          PropertyChangeListener pcl = new PropertyChangeListener() {
             public void propertyChange(PropertyChangeEvent evt) {
                String eventString = "Name: " + evt.getPropertyName() + ", " +
                   "Old Value: " + evt.getOldValue() + ", " + 
                   "New Value: " + evt.getNewValue();
                System.out.println(eventString);
             }
          };
          for (int i = 0; i < 10; i++) {
             MyPoint myPoint = new MyPoint();
             myPoint.setPoint(new Point(i, i));
             myPoint.addPropertyChangeListener(pcl);
             points.add(myPoint);
          }
          
          new Thread(new Runnable() {
             public void run() {
                for (MyPoint myPoint : points) {
                   Point p = myPoint.getPoint();
                   p = new Point(100 + p.x, 100 + p.y);
                   myPoint.setPoint(p);
                   try {
                      Thread.sleep(500);
                   } catch (InterruptedException e) {}
                }
             }
          }).start();
       }
    }
    
    class MyPoint {
       private Point point;
       private PropertyChangeSupport propChangeSupport = new PropertyChangeSupport(this);
    
       public Point getPoint() {
          return point;
       }
    
       public void setPoint(Point p) {
          Point old = point;
          this.point = p;
          propChangeSupport.firePropertyChange("point", old, p);
       }
    
       public void addPropertyChangeListener(PropertyChangeListener listener) {
          propChangeSupport.addPropertyChangeListener(listener);
       }
    
       public void removePropertyChangeListener(PropertyChangeListener listener) {
          propChangeSupport.removePropertyChangeListener(listener);
       }
       
       @Override
       public String toString() {
          return String.format("[%d, %d]", point.x, point.y);
       }
    
    }

  13. #13
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    Quote Originally Posted by Jonah Bron View Post
    Okay, here it is. This fails, with the same error as before: "Invalid thread access".
    Which line causes this? To be honest, I couldn't reproduce that error, but my compiler complained that the setLabel method wasn't defined.

    Again, I know nothing about SWT, but could tell you lots about doing something like this in Swing.

  14. #14
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Default

    Cool, thanks. Tomorrow I'll adapt that code to my application, and see if it works.
    Which line causes this? To be honest, I couldn't reproduce that error, but my compiler complained that the setLabel method wasn't defined.
    The error is in Observer, where it calls message.setText(msg). Strange that you don't get that error...

    Why do you prefer Swing over SWT/other gui toolkits? I picked SWT for the native widgets. I'm probably too far along to change it (without some significant refactoring, plus learning a different gui toolkit), but maybe you can convince me to use it on my next project?

  15. #15
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    I chose Swing after I had spent quite a bit of time at this and other fora such as the Sun Fora and JavaRanch and did so for several reasons, but mainly because I saw that there were many more folks using Swing vs. SWT and that while the Swing forums were usually alive and in fact bristling with activity, the SWT fora were pretty dead. So out of selfishness, I figured that if I ever had a problem, I could get it answered if I coded in Swing vs. SWT. Seems pretty silly ,right? But now I've grown to respect and yes, even love Swing and what it's taught me about model viewer relationships and Observer patterns.

  16. #16
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Default

    Okay, I figured that SWT must provide an easier way of doing this. So I googled "swt widget thread", and came up with this:

    SWT and Thread : Thread**SWT JFace Eclipse**Java

    Which presents the Display method syncExec(Runnable). In my SSCCE, it works. I'll try to integrate it into my app now.

  17. #17
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Cool

    Awesome, it's working now. The syncExec() method was the key. Thanks again for your help, Fubarable!

    Edit: oops, problem not really solved. It makes the GUI hang.

    Edit 2: Okay, I got it fixed after all. I was confused a bit, but this article helped me fix it.
    http://book.javanb.com/swt-the-stand...5lev1sec7.html
    Last edited by Jonah Bron; 10-28-2010 at 01:12 AM.

  18. #18
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

  19. #19
    Jonah Bron's Avatar
    Jonah Bron is offline Member
    Join Date
    Sep 2010
    Location
    California
    Posts
    26
    Rep Power
    0

    Default

    By the way, I took the example in the link I gave and put it into an Observer/Observable setup, and it will be further changed to place the handling of the Observer/Observable into the Command pattern.

Similar Threads

  1. KeyAdapter won't fire
    By billq in forum New To Java
    Replies: 5
    Last Post: 04-14-2010, 02:37 AM
  2. Replies: 2
    Last Post: 04-12-2009, 10:39 AM
  3. How to send event from thread to GUI?
    By mikeeve in forum New To Java
    Replies: 3
    Last Post: 03-13-2009, 02:33 AM
  4. Fire j2me 2.0 alpha
    By Java Tip in forum Java Software
    Replies: 0
    Last Post: 07-29-2008, 04:24 PM
  5. Fire j2me 1.2
    By JavaBean in forum Java Software
    Replies: 0
    Last Post: 06-21-2007, 11:46 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •