Android: Synchronizing Threads and Handler

20,042

You are implementing a couple of threads, and the order of the operations you are trying to do is not deterministic.

For example, it is possible "showFrame.Runable().run()" executed before getFrame.Runable().run().

  1. The "synchronize" key word does not help because when the work is down in separate thread. The synchronize function call will return, and lock will be released.
  2. The "locks" does not help to make sure the right order as well.

My suggestion is to use AsyncTask, http://developer.android.com/reference/android/os/AsyncTask.html. You can do something like this:

private class ProcessFrameTask extends AsyncTask {

 protected void doInBackground(Object... objs) {
     getFrame(); // Copy the frame
     calculateFrame(); // Do your magic
 }

 protected void onPostExecute(Long result) {
     showFrame(); // Post the result back to main thread
 }

}

No multiple threading and cooperation, just one Worker thread does all the work, and post the result back to main thread.

Share:
20,042
Admin
Author by

Admin

Updated on October 26, 2020

Comments

  • Admin
    Admin over 3 years

    I am having some trouble with my App. I'm very new to Android development so i hope it's an easy mistake. So I'm trying to write an app that gets some raw data via Wifi(first Thread), do some calculations(second Thread), create a Bitmap out of the calculated Data(third Thread) and update the Display(Handler). Some Parameters are adjusted by SeekBars. Everything works fine. But sometimes when I change the seekBarValues the Picture isn't updated Anymore. the Threads and the Handler are still running so i dont't get an Error.

    Here some Code:

    MainActivity:

    public class MainActivity extends Activity implements OnClickListener {
        private Handler outputHandler = new Handler();
        private SeekBar  seekBarBrightness,
        seekBarContrast,
        seekBarGamma;
    
        public static volatile double gamma = 1;
        public static volatile double brightness = 500;
        public static volatile double contrast = 500; 
        public static volatile double min = 0;
        public static volatile double max = 0;
    
        public static volatile boolean isRunning = false;
    
        public static volatile int r = 0;
        public static volatile int g = 0;
        public static volatile int b = 0;
        public static volatile int width = 400;
        public static volatile int height = 250;
    
        public volatile double inputExchangeFrame[][ ]= new double[400][250], outputExchangeFrame[][]= new double[400][250];
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
    
            seekBarBrightness = (SeekBar) findViewById(R.id.seekBarBrightness); 
            seekBarContrast = (SeekBar) findViewById(R.id.seekBarContrast);
            SeekBarGamma = (SeekBar) findViewById(R.id.seekBarGamma);
    
            newImage = Bitmap.createBitmap(width, height, BitmapConfig.ARGB_8888);              
            picture.setImageBitmap(newImage);
    
    
        }    
    
        @Override   
        public void onClick(View v) { 
            if(v==toggleButtonStartStop){
                if(toggleButtonStartStop.isChecked()==true){ 
                    isRunning=true; 
                    getFrame();
                    calculateFrame();
                    showFrame();
                }
                else{ 
                    isRunning = false;
                }
            }
        }            
    }
    

    And the Other Methods declared also in MainACtivity: getFrame():

    private synchronized void getFrame(){
         inputThread = new Runnable(){
              public void run(){
                   while(isRunning == true){
    
                       //inputFrame fron WIFI
    
                        inputExchangeFrameLock.lock();
                        //synchronized(inputExchangeFrame){
                             for(int x_1=0 ; x_1<width ; x_1++){
                                  for(int y_1=0 ; y_1<height ; y_1++){
                                       inputExchangeFrame[x_1][y_1]=inputFrame[x_1][y_1];
                                  }
                             }
                        //}
                       inputExchangeFrameLock.unlock();
    
                       try {                        
                            Thread.sleep(120);
                       } 
                       catch (InterruptedException e) {
                            e.printStackTrace();
                       }
                  }
             }
         };new Thread(inputThread).start();
    };
    

    calculateFrame:

    private synchronized void calculateFrame(){
         calculationThread = new Runnable(){
              public void run(){
                   while(isRunning == true){    
                   //get Data from InputThread to applicate several Filter
                   inputExchangeFrameLock.lock();
                   //synchronized(inputExchangeFrame){
                        for(int x_2=0 ; x_2<width ; x_2++){
                             for(int y_2=0 ; y_2<height ; y_2++){
                                  calculationFrame[x_2][y_2]=inputExchangeFrame[x_2][y_2];
                             }
                        }
                   //}
                   inputExchangeFrameLock.unlock();
    
                     //Do some calculations on calculationFrame  
    
                   outputExchangeFrameLock.lock();
                   //synchronized(outputExchangeFrame){ 
                        for(int x_3=0 ; x_3<width ; x_3++){
                             for(int y_3=0 ; y_3<height ; y_3++){
                                  outputExchangeFrame[x_3][y_3] = calculationFrame[x_3][y_3];
                             }
                        }
                   //}
                   outputExchangeFrameLock.unlock();
                   }
              }
         }; new Thread(calculationThread).start();
    };
    

    showFrame():

    private synchronized void showFrame(){
         outputThread = new Runnable(){
              public void 
                   while(isRunning == true){
                        contrast =  seekBarContrast.getProgress() +1;
                        brightness = seekBarBrightness.getProgress() + 1;
                        gamma = seekBarGamma.getProgress() + 1;
    
                        outputExchangeFrameLock.lock();
                        //synchronized(outputExchangeFrame){
                        for(int x_4=0 ; x_4<width ; x_4++){
                             for(int y_4=0 ; y_4<height ; y_4++){
                                  outputFrame[x_4][y_4] = outputExchangeFrame[x_4][y_4];
                              }
                         }  
                         //}
                         outputExchangeFrameLock.unlock();
    
                         for (int x_14=0 ; x_14<width ; x_14++){
                              for(int y_14=0; y_14<height; y_14++){
    
                                 //Calculation of r,g,b  using gamma, brightness and contrast
                              }
                              synchronized(newImage){
                                   newImage.setPixel(x_14, y_14, Color.rgb(r,g,b));
                              }
                         }
    
                         outputHandler.removeCallbacks(pictureUpdate);
                         outputHandler.post(pictureUpdate);
    
                         try {
                              Thread.sleep(50);
                         } 
                         catch (InterruptedException e) {
                              e.printStackTrace();
                         }
                    }
               }
         }; new Thread(outputThread).start();   
    };
    

    and the Handler:

    private Runnable pictureUpdate = new Runnable(){
    public void run(){ synchronized(newImage){ picture.setImageBitmap(newImage);
    } }
    };

    I know thats a lot of Text. But I really don't know where to start searching and what I could do to find the mistake.

    Any suggestions would be great!

    thanks

    Michael