java Android:同步线程和处理程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16018040/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 21:37:52  来源:igfitidea点击:

Android: Synchronizing Threads and Handler

javaandroidsynchronizationhandlerseekbar

提问by user2282554

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.

我的应用程序遇到了一些问题。我对 Android 开发很陌生,所以我希望这是一个简单的错误。所以我正在尝试编写一个应用程序,通过 Wifi(第一个线程)获取一些原始数据,进行一些计算(第二个线程),从计算出的数据(第三个线程)中创建一个位图并更新显示(处理程序)。一些参数由 SeekBars 调整。一切正常。但有时当我更改 seekBarValues 时,图片不再更新。线程和处理程序仍在运行,所以我没有收到错误消息。

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():

以及在 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);
} }
};

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

迈克尔

采纳答案by dongshengcn

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().

例如,可以在 getFrame.Runable().run() 之前执行“showFrame.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.
  1. “同步”关键字没有帮助,因为当工作在单独的线程中停止时。同步函数调用将返回,并且锁将被释放。
  2. “锁”也无助于确保正确的顺序。

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

我的建议是使用 AsyncTask,http://developer.android.com/reference/android/os/AsyncTask.html。你可以这样做:

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.

没有多线程和协作,只有一个 Worker 线程完成所有工作,并将结果发布回主线程。