Android: die Synchronisation von Threads und Handler
Ich habe einige Probleme mit meiner App. Ich bin sehr neu in Android Entwicklung so hoffe ich, es ist ein Fehler.
Also ich bin versucht, zu schreiben eine app, erhält einige raw-Daten via Wifi(Erster Thread), einige Berechnungen(zweiten Thread), erstellen Sie eine Bitmap aus der berechneten Daten(Dritte Thread) und aktualisieren Sie die Anzeige(Hf).
Einige Parameter werden eingestellt, indem SeekBars. Alles funktioniert einwandfrei. Aber manchmal, wenn ich die seekBarValues das Bild nicht Mehr aktualisiert. die Threads und Handler werden immer noch laufen, damit ich nicht eine Fehlermeldung erhalten.
Hier einige 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;
}
}
}
}
Und die Anderen deklarierten Methoden auch in der 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();
};
zeigerahmen():
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();
};
und der Hf:
private Runnable pictureUpdate = new Runnable(){
public void run(){
synchronisiert(newImage){
Bild.setImageBitmap(newImage);
}
}
};
Ich weiß, das ist viel Text. Aber ich weiß wirklich nicht, wo die Suche beginnen soll und was ich tun könnte, den Fehler zu finden.
Irgendwelche Vorschläge wäre toll!
Dank
Michael
InformationsquelleAutor user2282554 | 2013-04-15
Du musst angemeldet sein, um einen Kommentar abzugeben.
Implementieren Sie ein paar Fäden, und die Reihenfolge der Operationen, die Sie versuchen zu tun, ist nicht deterministisch.
Beispielsweise ist es möglich, "zeigerahmen.Lauffähige().run()" ausgeführt, bevor getFrame.Lauffähige().run().
Mein Vorschlag ist die Verwendung von AsyncTask, http://developer.android.com/reference/android/os/AsyncTask.html. Können Sie etwas wie das hier tun:
}
Kein multiple threading und Zusammenarbeit, mit nur einem Worker-thread erledigt alle Arbeit, und poste das Ergebnis zurück an den Haupt-thread.
1. Mehrere Threads in der Regel nicht den Durchsatz zu erhöhen. Vielleicht ist es funktioniert, wenn Sie haben mehrere Kerne, und Sie können tun einige Tests, um zu sehen, dass. 2. Wenn der Flaschenhals ist wifi, und Sie möchten, die Benutzer, um die Daten zu sehen, wie es kommt, verwenden Sie den java.util.Auger für mehrere threading nicht umsetzen, sondern Ihre eigenen. Eine einfache Möglichkeit ist ein thread auf Daten wartet, und post zu einem anderen thread zu verarbeiten, wenn es genug Daten.
So, jetzt ich habe versucht, Ihre Lösung. Leider das gleiche problem. Alles funktioniert gut, aber manchmal ist das Bild nicht mehr aktualisiert, nachdem ich die geändert seekBarValue. Ich habe versucht, einige USB-Debugging und jetzt bekam ich diese Fehlermeldung: "OpenGLRenderer generieren Kann, die textur von bitmap". Ist es möglich, dass der Fehler ist, dass mein Bild hat weniger Pixel als die Bildansicht? Ich wollte android zu interpolieren automatisch. Aber es scheint, dass ich habe, dies zu tun auf meinem eigenen. Oder ist es ein anderes problem. Dank
Ich bin nicht sicher, was das problem ist. Ein stack-trace wäre schön. Und, auch versuchen zu trennen, die ängste, indem Sie sicherstellen, dass Ihr code funktioniert, ohne threading-code.
Ich denke, dass ich das problem gelöst. Ich bin mir nicht sicher, aber ich denke, die app wollte die Bitmap aus einem Objekt, das markiert war, wird für die GC zu zerstören. So wurde das Objekt noch da, aber konnte nicht verwendet werden, um die Anzeige zu aktualisieren. Das ist, warum gab es keine Fehlermeldung. Ich jetzt erstellen Sie ein neues Bitmap-Objekt mit jeder Schleife die Bitmap wird berechnet, und es scheint, dass es funktioniert. Ich werde den AsyncTasak Lösung, die Sie empfohlen. Es ist viel einfacher zu synchronisieren. So ich danke Ihnen sehr. Hat mir sehr geholfen!
InformationsquelleAutor dongshengcn