Loading...
Logo
Processing Forum
I've recently started using multiple threads (-so it is likely I'm making mistakes there-) when I came accross the following problem:
My main routine (in draw()) clears the background and draws on it, as usual. Some other threads "prepare" things to be drawn, and they are drawn in a PGraphics buffer first (using both JAVA2D and P2D). Only when they are finished, the objects are used in the main thread.
That works nicely.  However, every so often in a not quite regular way, my main drawing routine seems to "flicker" by displaying what seems to be a blue background for a very short time, while turning a grey rectangle red.
 
Now, I do not use blue at ANY time in my sketch, so where does it come from? Ideas?
 
Worthwhile mentioning: I don't seem to have the problem without using mutliple threads, and those threads do prepare graphics.

Replies(10)


Only when they are finished, the objects are used in the main thread.
How do you make sure they are finished before they are used in the main draw() method because this is the most likely cause of the flickering.
It is probably caused by the draw() method trying to used partially updated data for instance you are changing the x and y positions of something to be drawn the x gets updated then the draw method does its stuff before the y gets updated. There are several mechanisms that can be used to resolove this I will describe the easiest to implement.

Assume we have some data shared by the two methods draw and update, where update is running in a separate thread.

Create a boolean variable called dataLock which is assessable to both threads now in draw we have the code
Copy code
  1. void draw(){
  2.       if(dataLock == false){
  3.             dataLock = true;       // grab a lock on the data
  4.             background(0);
  5.             // rest of our code goes here

  6.             dataLock = false;      // release the lock on the data
  7.       }
  8. }
If dataLock is true the draw method is aborted and the screen remains unchanged.


Now the update code is in a separate thread which our sketch has created so we have full control over this.
Copy code
  1. void update(){
  2.       while(dataLock == true){
  3.             try{
  4.                   sleep(10);      // pause this thread for 10 milliseconds
  5.             }
  6.             catch(Exception excp){
  7.             }
  8.       }
  9.       dataLock = true;            // grab control of the data
  10.       // update the data

  11.       dataLock = false;            // release the lock
  12. }
If dataLock is true then the data is being drawn so we pause the thread until the data has been released by the draw method before updating it.

Doing it this way means that the update will always get done even if we have to wait a few millis.

This assumes you are creatinng your own classes that extend the Thread class rather than implementing runnable. Personally I prefer extending Thread as it gives you greater flexibility in how you use/ control the thread created.





Thanks for the info.
I was doing something similar to this.
I've started out my sketch (which is rather a lot of code, thus not copied here) without threading and later learnt of threading (actually last week) and tried to "hack it into" aftwards. So there might be problems there, although I don't see them right now.
In a strongly reduced version, this is what my sketch does:
 
ArrayList List;
myObClass myOb;

void setup(){
   List = new ArrayList();
   for (int i=0;i<10;i++){
     myOb = new myObClass();
     myOb.prepare();
     List.add(myOb);
   }
}

void draw(){
    int nrObjects = List.size();
    println("List size:"+nrObjects);
    for (int i = 0;i
               
                get(i);
      
                if (!myOb.ready) 
                continue;
      myOb.DoSomething();
    }
    
                if (somethingInterestingHappens()) {
        myOb = 
                new myObClass();
        myOb.prepare();
        List.
                add(myOb);
    }
  }
  
 
                boolean somethingInterestingHappens(){
   
                if (
                random(0,1)<0.1) 
                return 
                true;
   
                return 
                false;
 }
  
 
                class myObClass 
                implements Runnable 
 {
   
                boolean ready=
                false;
   
                Thread thread;
    
   myObClass(){}
   
                public 
                void run() {
     
                //[... do a lot, i.e. prepare an array of images using other class functions]
     ready = 
                true;
     }
   
                void DoSomething(){
     }
   
                void prepare()   {
      ready = 
                false;  
      
                if (thread!=
                null) 
                return;
      thread = 
                new 
                Thread(
                this);
      thread.start();
     }   
 }


               
some comments:
The "prepare()" routine might be called not only at adding a new object, but also later in the sketch if some parameters are changed, which change the object-appearance. Thus check if there already is a thread running in prepare() (In which case, the object is not updated. It gets rendered "false" though, so next frame it tries again...
 
What puzzels me about the flickering: Where does the BLUE color come from? Is there anywhere within processing/java a "blue screen" or is this a hint of where my problem might be?
 
Just an idea: My sketch does change the colorMode() from RGB to HSB and back several times. It does so, however, in the "enclosed" PGraphics. Is the colorMode() valid for ALL of the script or for the PGraphics object only?
You have a interesting syntax for the for loop in draw but I managed to sort it out and play with the code.

It seems to work fine in that it runs without causing exceptions, but it all really depends on what you you do inside the run method, provided you are not attempting to draw (e.g. rect(), ellipse() etc) or modify something used for drawing (e.g. stroke(), fill(), rectMode() etc) then I am not sure what is causing your screen flicker.
 
Oups. Copy & paste seemd to have messed it
 
Well, my "run" does use drawing methods, but only on the internal graphic buffers, not oto the screen.
Ok so the run() method draws to the internal graphic buffers and I assume that the draw() method copies part or all of the buffer data to the main screen.

This maybe your problem in that the draw() thread is given control while run() method is part way through updating the graphic buffers. The code you have shown does not prevent this.

Keep the draw methods as before i.e.
Copy code
  1. void draw(){
  2.   if(dataLock == false){
  3.     dataLock = true;       // grab a lock on the data
  4.     background(0);

  5.     // can use graphic buffer data

  6.     dataLock = false;      // release the lock on the data
  7.   }
  8. }

and change the run method to something like this
Copy code
  1. void run(){
  2.   while(thread != null){
  3.     while(dataLock == true){
  4.       try{
  5.         sleep(10);      // pause this thread for 10 milliseconds
  6.       }
  7.       catch(Exception excp){
  8.       }
  9.     }
  10.     dataLock = true;            // grab control of the data

  11.     // update the internal graphic buffers here

  12.     dataLock = false;            // release the lock
  13.    
  14.     // You may want a small delay here for the main
  15.     // thread to have a chance to do something
  16.     try{
  17.        sleep(10);      // pause this thread for 10 milliseconds
  18.     }
  19.     catch(Exception excp){
  20.     }
  21.    
  22.   } // end while thread
  23. }

This will prevent the draw method from executing while the graphic buffers are being updated.

Hmm.
While I appreciated your comment (-in particular the way you catching the exception in the run()-), I'm not sure it is my problem.  At least, not that I could see it. Although my "run()" routine draws into internal graphic buffers (three differnt PGgraphics, two Java2D one P2D), non of it is the actual screen or a buffer used from within draw(). Instead, all the drawing ends up bying placed in an array of Pimages (during the run()) which is part of the object.
draw() accesses this array only, once the object is ready (myObj.isready=true) and this is only done at the end of my run().
I don't use global variables.
 
So, unless differernt PGraphics can "interfere" with each other, I don't seem to be able to find the weak spot.

So, unless different PGraphics can "interfere" with each other, I don't seem to be able to find the weak spot.
With all those threads maybe your sketch that gets confused about which 'canvas' it is drawing to?

Using multiple threads is hard enough with standard Java but is more challenging with Processing perhaps someone else has some ideas?

Thanks for all your help. I think, yesterday I finally found the problem after some very carefuly screening the code.
It was indeed a call of colorMode() which I've overlooked in the run() thread. So, what happened is, that the colorMode got changed to HSB in the run() and the background(120,120,120) changed its meaning...
 
Which now gives rise to a different question, but I rather post that separately.
It is interesting that the HSB colorMode caused the problem since I too have had similar issues with some of my sketches  - they will occasionally after some interaction turn all white to blue. As far as I am aware, there are no colorMode calls in the sketches that do this, nor do I explicitly create separate threads (other than have activity in the draw and mouse/keyboard methods that themselves run on different threads).

It is a remarkably difficult problem to identify since it happens rarely, and is not easy to reproduce on demand.