ProgressMonitor painting problem


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 4 of 4

Thread: ProgressMonitor painting problem

  1. #1
    Join Date
    Jun 2005
    Posts
    2

    Question ProgressMonitor painting problem

    Hello,

    I'll try to be clear, ask me anything if it isn't. I have two threads, one that downloads some selected webpages, and the other that reads them. In the thread that reads, there is a ProgressMonitor object, which indicate how many webpages have been read.

    I created a JUnit test which works as expected. One thread downloads, the other reads and a nice little progress monitor appears and everything works.

    I transfered the code (the part of the code starting the thread that reads, which starts the thread that downloads) into the main application. The threads are working and the ProgressMonitor appears, but it does not draw the components (there is no label, progress bar, button etc...). I can't seem to find the problem. I think it is caused by the threads or synchronized methods, I am not sure as I am no expert with threads. Once the threads have finished running, the components of the ProgressMonitor appears. So I guess that the threads are blocking the (re)painting of the application, but I can't figure why. Im using Thread.yield() quite often. Priorities problem ? Here some parts of the code :

    JUnit Test code :
    Code:
    public class HarvesterTests extends TestCase {
    
    	public synchronized void testHarvest() {
    				
    		JFrame frame = new JFrame("Dummy");
    		frame.setVisible(true);
    		
    		Harvester harvester = new Harvester(
    				frame,
    				new Rule());
    		Thread harvest = new Thread(harvester);
    		
    		harvest.start();
    		
    		while (!harvester.isFinished()) {
    			try {
    				Thread.sleep(500);
    			} catch (InterruptedException ie) {}
    		}
    }
    Main application :

    Code:
    public class Gui extends JFrame implements ComponentListener {
    ...
    private static	JFrame	mMotherFrame	=	null;
    ...
    
    public Gui() {
    ... mMotherFrame = this; ...
    }
    private class GuiActionRealize {
    ...
    public synchronized void getFromWeb() { Harvester harvester = newHarvester( mMotherFrame, new Rule()); Thread harvest = new Thread(harvester); harvest.start(); while (!harvester.isFinished()) { try { Thread.sleep(500); } catch (InterruptedException ie) {} } ... }
    Harvester :

    Code:
    public class Harvester implements Runnable {
    ...
    private JFrame mMotherFrame;
    private ProgressMonitor mMonitor;
    ...
    	public Harvester(JFrame owner, IRule subjectRule) {
    		...
    		mMotherFrame = owner;
                    ...
    	}
    ...
    
    
    public void find() ... mMonitor = new ProgressMonitor(mMotherFrame, "Downloading decisions from the Internet.", "", 1, mAcceptedURLs.size()); mMonitor.setMillisToDecideToPopup(0); mMonitor.setMillisToPopup(0); ... }
    public void run() { find(); mHarvested = harvest(); mFinished = true; Thread.yield(); } ... public List harvest() { ... download = new DownloadThread(this, mAcceptedURLs); ... Thread downthread = new Thread(download); downthread.start(); int i = 0; while (!mMonitor.isCanceled()) { while (download.getDownloadedDocuments().isEmpty()) { try { Thread.yield(); Thread.sleep(300); } catch (InterruptedException ie) {} } ... mMonitor.setNote("Downloading decision " + i); mMonitor.setProgress(mMonitor.getMinimum()+ ++i); } // end while(!cancel) download.kill(); return mHarvested; } ... }
    I'm very puzzled by the fact that it worked in the JUnit Case and not in the application.

    Any help about this problem is appreciated
    Thank you in advance.

  2. #2
    Join Date
    Nov 2004
    Location
    Norway
    Posts
    1,560
    I haven't looked closely on your code fragments here, but yield() won't help if the
    thread that is doing the gui update is waiting for the process that delivers gui update
    info to finish. I think you should try to create the gui separately from the other thread
    processing; start a thread that creates the gui, then the reader thread that joins
    the gui thread, i.e. waits for the gui setup processing to finish.

    Just one ting:
    Code:
    private class GuiActionRealize {
    ...
      public synchronized void getFromWeb() {	
    	Harvester harvester = newHarvester(
    					mMotherFrame,
    					new Rule());
    	Thread harvest = new Thread(harvester);
    			
    	harvest.start();
    			
    	while (!harvester.isFinished()) {
    		try {
                                    // as far as I can see it is the thread that 
                                    // created/started harvest that sleeps here
                                    //...not harvest, to wait for it you should use
                                    // harvest.join(),  if that is what you want....
    		      Thread.sleep(500);
    		} catch (InterruptedException ie) {}
    	}
    ...
    }
    Last edited by sjalle; 06-06-2005 at 06:47 PM.
    eschew obfuscation

  3. #3
    Join Date
    Jun 2005
    Posts
    2
    Thank you for the advice, unfortunately, it doesn't seem to fix the problem. I agree that using the join() method is a much better choice than the while loop I first thought.

    I may have misunderstood what you wrote, but I don't think I can divide the gui from the harvest thread easily, since it's an ActionEvent that calls the getFromWeb() method. Here's the complete path from the Gui to the getFromWeb() method :

    Gui -> JButton -> ActionEvent -> GuiActionDispatch.actionPerformed -> GuiActionRealizer.getFromWeb()

    GuiActionDispatch is an object that catches the ActionEvent and calls the appropriate method in the object GuiActionRealizer. (It's a large application so I need to divide for better clarity...)

    Since yesterday I have tried other things with no success. (Priorities, dummy JFrame that is used has the owner frame). I still cannot understand why it worked so well in the JUnit test and not on the main application.

    Here's another thing that I tried, so it would look as most possible to the JUnit test :

    Code:
    		public synchronized void getFromWeb() {
    			
    			JFrame dummy = new JFrame();
    			dummy.setVisible(false);
    	
    			JudgementHarvester harvester = new JudgementHarvester(
    					dummy,
    					new ImmigrationSelectionRule());
    			Thread harvest = new Thread(harvester);
    
    			harvest.start();			
    			
    			try {				
    				harvest.join();
    			} catch (InterruptedException ie) {}
    			
    ...
    I can see that the thread that is responsible for drawing components is not doing his job, since that the mother frame (Gui class) is not being repainted while the harvest/download threads are working. That's not the case in the JUnit case, where the frame is being repainted and everything is fine. This is the only place in the application that I'm using threads/runnable objects.

    I also tried making the Gui class a thread by implementing the Runnable interface, and creating the run method with only a repaint() statement.

    And I tried setting the priority of the harvest thread to the minimum. No luck.

    If you need more info/code, let me know, Ill try to give as much info as I can.
    Thank you

  4. #4
    Join Date
    Nov 2004
    Location
    Norway
    Posts
    1,560

    I have made something similar...

    ...that you might want to have a look at

    Its a GUI that receives display data from multiple processes, these are
    simultameusly running http requests. Even if these processes have the
    same display as target they queue up so the output doesn't get mixed.

    The clue is 'smart threads'.

    I have it here (my free java source lib)

    http://home.no.net/sjalle/Library.html (its a swing applet)

    The file name is ThreadedGUI.zip

    I have never used JUnit but obviously the GUI is threaded differently in
    that scenario than in the 'real world'.

    Btw, how big is the application (codelines count/class count) ?, is it too
    big to zip and mail to me (or do you want it to be a secret ) ?
    Last edited by sjalle; 06-07-2005 at 11:08 AM.
    eschew obfuscation

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center