Calling a Thread from another Class

Hi. Im having this weird issue, I don't know how to deal with it.

I want to call from inside a class another class that uses a thread. But I get illegal exceptions. The first class creates a slideshow - returning a pgraphics that I draw in my main function. The second class is supposed to load the files on the background (for PImage), that are used then in the first class.

Here is an example that illustrates my practice:

class ImageSlide {
  // Create a new object for the tread class inside this class  
  LoadFiles loadFiles;

  PGraphics pg;

  ImageSlide() {
    loadFiles = new LoadFiles();
    pg = createGraphics(212, 184);
  }

  void loading() {
    loadFiles.start();
  }

  PGraphics runGraphics() {
    pg.beginDraw();
    pg.image(imageOne, 0, 0);
    return pg;
  }
}

//This is the tread class that loads the files independently
public class LoadFiles extends Thread {
  private boolean running;

  public LoadFiles (){
    running = false;

    path = dataPath("");
    fp = new File(path);
    fpCheck = new File(path);
    namesFilesPath = fp.list(); 
    fileArrayList = new ArrayList<String>();

    presetImage = loadImage("preset.png");
    presetImage.resize(212, 184);
  }

  public void start () {
    running = true;
    System.out.println("Starting thread for loading files...");
    super.start();
  }

  public void run () {
    //Load a random file from the data folder if new imags have been loaded
    namesFilesPath = fp.list(); 
    for (int i=0; i<namesFilesPath.length; i++) {
      if (namesFilesPath[i].toLowerCase().endsWith(".jpg")) {
        fileArrayList.add(namesFilesPath[i]);
      }
    }

    loadImageOne();

    System.out.println("Load Thread is done!");
  }

  void loadImageOne() {
    if (fileArrayList.size() > 0) {
      imageOne=loadImage(fileArrayList.get( (int)random (fileArrayList.size())));
      imageOne.resize(212, 184);
    }
    else {
      imageOne=presetImage;
    }
  }

  public void quit() {
    System.out.println("Quit");
    running = false;
    interrupt();
  }
}

Answers

  • edited November 2013

    AFAIK, a Thread instance can't be run more than once! To re-run it, you gotta create another instance of it! @-)

  • I suspect at line 18 you should have

    PGraphics runGraphics() {
      pg.beginDraw();
      pg.background(255); // clear the backgorund in case nothing to draw
      if(imageOne != null) // may not have loaded yet ???
          pg.image(imageOne, 0, 0);
      pg.endDraw(); // needed to match beginDraw
      return pg;
    }
    
  • edited November 2013

    GoToLoop: For sure, I call it every time I need it to process information for me. This happens in the first class here:

    void loading(){
        loadFiles.start();
    }
    

    And I call this function from my main program in my setup (and draw function not constantly, only when I want a new result)

    imageSlide[i].loading();

    quark: I did this, not much things changed - concerning my errors. I suspect it is a problem with the threat?

  • illegal exceptions

    What types of exception are you getting?

  • edited November 2013

    We can't invoke method start() more than once for each instance of Thread!!! b-(

  • I am not sure, but I think you should create a new instance of LoadFiles each time you need to run a new thread.

    The quit() method seems a bit useless. A thread stops when its run() method returns.

  • edited November 2013 Answer ✓

    GoToLoop is right, see Thread: "It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution."

    Better check reference than supposing things (from observed practice).

  • Does this mean that I should create an array of Thread classes that are "synced" with the ImageSlide class? I mean, each ImageSlide class should call its own thread? It seems a bit unorthodox this configuration, am I right? I will try and see what happens.

    Thanks btw!

  • You can re-use a previous variable. Just re-instantiate the Thread class! L-)

  • edited November 2013

    Here is a simple demonstration of loading images in thread and use them outside the class. I will try to extend the concept to fit my purpose.

    LoadFilesThread1 loadThread1;
    
    PImage imageOne;
    int x = 0;
    
    void setup() {
      size(400, 400);
      imageOne = loadImage("loading.png");
      loadThread1 = new LoadFilesThread1();
      loadThread1.start();
    }
    
    void draw() {
      println(x);
      image(imageOne, 0, 0);
    }
    
    public class LoadFilesThread1 extends Thread {
    
      public LoadFilesThread1 () {
    
      }
    
      public void start () {
        System.out.println("Starting thread");
        super.start();
      }
    
      void run() {
        getImage();
        println("thread is done");
      }
    
      void getImage() {
        x = 10;
        imageOne=loadImage("preset.png");
        imageOne.resize(width, height);
      }
    }
    
  • edited November 2013

    So, new issue. Following, I use the 'a' key to trigger a new thread. However, this should be valid if no previous threads run - I use a boolean to check the state of the thread, and to give me true when the thread has finished its execution.

    I get an IllegalThreadStateException

    ***Edit: I added the following line and I don't get the exception as I rebuild the thread from the beggining.

    loadFiles1 = new LoadFiles1();

    LoadFilesThread1 loadThread1;
    
    PImage imageOne;
    boolean checkNewFile = false;
    boolean threadFinished = false;
    
    void setup() {
      size(400, 400);
      imageOne = loadImage("0.jpg");
      imageOne.resize(width, height);
    
      loadThread1 = new LoadFilesThread1();
      //loadThread1.start();
    }
    
    void draw() {  
      background(0);
    
      println(threadFinished);
    
      threadFinished = false;
    
      if (checkNewFile) {
        if (!threadFinished) {
          loadFiles1 = new LoadFiles1();
          loadThread1.start();
        }
        checkNewFile = false;
      }
      image(imageOne, 0, 0);
    }
    
    void keyReleased() {
      if (key == 'a') {
        checkNewFile = true;
      }
    }
    public class LoadFilesThread1 extends Thread {
    
      public LoadFilesThread1 () {
      }
    
      public void start () {
        threadFinished = false;
        System.out.println("Starting thread");
        super.start();
      }
    
      void run() {
        getImage();
        threadFinished = true;
        println("thread is done");
      }
    
      void getImage() {
        imageOne=loadImage( (int) random (4) + ".jpg" );
        imageOne.resize(width, height);
      }
    }
    
Sign In or Register to comment.