How to call thread("functionName") in draw()

edited October 2016 in How To...

How to call thread("functionName") in draw() with when the function is in a class in other tab? if I put the function in the main class, it has no problem. If I put them in a class in other tab, I get "There is no public functionName() method in the class xxxxxx" msg.

Answers

  • edited October 2016 Answer ✓

    Function thread() can only call PApplet methods of the same instance.
    It uses reflection internally and can't see methods from other classes.

  • And to answer your next question, you could manually create a Thread instance and call whatever function you want from its run() function.

    However, you should be really absolutely positively sure that you need to use threading before you do this.

  • edited October 2016

    Thanks guys, but let me make sure I fully understand. Here is the code example.

    String city = "";
    int direction = 0;
    float speed = 0;
    PFont font;
    XML myvalue, xml;
    
    void setup() {
      size(600, 360);
      String url = "http://" + "query.yahooapis.com/v1/public/yql?format=xml&q=select+*+from+weather.forecast+where+woeid=" + 1118370 + "+and+u='C'";
      xml = loadXML(url);
    }
    
    void draw() {
      background(255);
      fill(0);
      if (frameCount% 60 == 0) {
        thread("loadData");
      }
      text("City: " + city, width*0.15, height/2);
      text("Direction :"+direction, width*0.45, height/2);
      text("Speed :"+speed, width*0.75, height/2);
    }
    
    void loadData() {
      myvalue = xml.getChild("results/channel/yweather:wind");
      direction = myvalue.getInt("direction");
      speed = myvalue.getFloat("speed");
      myvalue = xml.getChild("results/channel/yweather:location");
      city = myvalue.getString("city");
    }
    

    Are you saying I can't put the loadData() in other class when I try to do OOP?

  • Are you saying I can't put the loadData() in other class when I try to do OOP?

    Yes. The loading class should either implement the Runnable interface or extend the Thread clas.

  • edited October 2016

    http://query.YahooApis.com/v1/public/yql?format=xml&q=select+*+from+weather.forecast+where+woeid=1118370+and+u='C'

    /**
     * Yahoo Weather XML (v2.2)
     * Julo & GoToLoop (2016-Oct-18)
     *
     * forum.Processing.org/two/discussion/18591/
     * how-to-call-thread-functionname-in-draw#Item_6
     */
    
    static final String URL =
      "http:/" + "/query.YahooApis.com/v1/public/yql" +
      "?format=xml&q=select+*+from+weather.forecast" +
      "+where+woeid=1118370+and+u='C'";
    
    static final String XML_PATH = "results/channel/yweather:";
    
    static final String LOCAL = "yql.xml";
    static final boolean IS_LOCAL = true;
    
    static final int INTERVAL = 5 * 60 * 1000; // 5 minutes
    
    String city, txt;
    int dir, cx, cy;
    float spd;
    
    void setup() {
      size(400, 360);
      smooth(3);
      frameRate(1);
    
      fill(0);
      textSize(32);
      textAlign(LEFT, CENTER);
    
      cx = width>>2;
      cy = height>>1;
    
      thread("grabXMLWeatherCast");
    }
    
    void draw() {
      background((color) random(#000000));
      text(txt, cx, cy);
    }
    
    void grabXMLWeatherCast() {
      for (;; delay(INTERVAL)) {
        final XML xml = loadXML(IS_LOCAL? LOCAL : URL);
    
        final XML wind = xml.getChild(XML_PATH + "wind");
        println(wind, ENTER);
        dir = wind.getInt("direction");
        spd = wind.getFloat("speed");
    
        final XML loc = xml.getChild(XML_PATH + "location");
        println(loc, ENTER);
        city = loc.getString("city");
    
        txt = "City: " + city + "\nDirection: " + dir + "\nSpeed: " + spd;
      }
    }
    
  • Thanks guys. GoToLoop, code not working?

  • edited October 2016

    Unfortunately not! The YahooApis.com returns "Bad Gateway 502". :(
    Seems like they don't like generic programs accessing their query? :-/
    Unless they can somehow pretend they're a browser? :ar!

  • Are you saying I can't put the loadData() in other class when I try to do OOP?

    I'm not sure I understand your question. But if you move the loadData() function, then you'll have to use the approach I outlined above: using a Thread to run it yourself instead of relying on the thread() function. It's not a ton of syntax:

    new Thread(){
       public void run(){
          //your code goes here, will run in another thread
       }
    }.start();
    

    But like I said, using threading (either by calling the thread() function or by creating your own Thread) introduces a ton of complexity, so make sure you really understand what's going on here.

    For example, since you're setting txt in one thread (and you're doing it in a way that takes mutliple steps) and drawing it in another, you could run into the case where txt is not fully set while you're drawing it. These types of bugs can be very hard to track down.

  • edited October 2016

    ... you could run into the case where txt is not fully set while you're drawing it.

    • There's no way for that to happen b/c reference variables store memory addresses.
    • And the memory address stored in variable txt only changes once the String segments are fully merged as 1 String.
    • Then the memory address of that last String is stored in variable txt, overriding the previous 1.
    • Notice that String class is immutable. Its state never changes unless we hack it w/ reflection! :ar!
  • Good to know!

    Still, @KevinWorkman 's basic statement that "using threading ... introduces a ton of complexity" remains good advice. And many threading bugs are very hard to track down. Processing attempts to hide some of that complexity by wrapping asynchronous behavior itself. Those wrappings are primitive -- thread() and loadData() don't support calling class methods in ways that are intuitive when trying to build an OOP pattern.

    1. Simple solution: break the loader method of your design out, make it a top-level function instead of a class method.
    2. Complex solution: implement your own Thread.
Sign In or Register to comment.