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
Android: Synchronizing Threads and Handler
提问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()”。
- 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.
- 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:
我的建议是使用 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 线程完成所有工作,并将结果发布回主线程。