Android: la Synchronisation de Threads et de Gestionnaire
Je vais avoir quelques soucis avec mon Application. Je suis très nouveau développement Android donc j'espère que c'est une erreur facile.
Donc, je suis en train d'écrire une application qui reçoit des données brutes via le Wifi(premier Thread), faire quelques calculs(deuxième Thread), créer une image Bitmap de Données calculées(troisième Thread) et mise à jour de l'Affichage(Handler).
Certains Paramètres sont ajustés par SeekBars. Tout fonctionne très bien. Mais parfois, quand je change le seekBarValues l'Image n'est pas Plus mis à jour. le Fils et le Gestionnaire sont toujours en cours donc je ne reçois pas une Erreur.
Voici un peu de 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;
}
}
}
}
Et les Autres Méthodes déclarées également dans 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();
};
et le Gestionnaire:
privé Praticable pictureUpdate = new Runnable(){
public void run(){
synchronisée(newImage){
image.setImageBitmap(newImage);
}
}
};
Je sais que c'est beaucoup de Texte. Mais je ne sais vraiment pas par où commencer la recherche et ce que je pourrais faire pour trouver l'erreur.
Toute suggestion serait génial!
grâce
Michael
OriginalL'auteur user2282554 | 2013-04-15
Vous devez vous connecter pour publier un commentaire.
Vous êtes à la mise en œuvre d'un couple de fils, et l'ordre des opérations que vous essayez de faire n'est pas déterministe.
Par exemple, il est possible de "showFrame.Runable().run()" exécuté avant getFrame.Runable().run().
Ma suggestion est d'utiliser des AsyncTask, http://developer.android.com/reference/android/os/AsyncTask.html. Vous pouvez faire quelque chose comme ceci:
}
Pas de multiples threading et de la coopération, juste un thread fait tout le travail, et d'afficher les résultats de thread principal.
1. Plusieurs thread n'est généralement pas augmenter le débit. Peut-être qu'il ne si vous avez plusieurs cœurs, et vous pouvez faire quelques test pour voir que. 2. Si le goulot d'étranglement est en wifi, et que vous voulez l'utilisateur de consulter les données comme il arrive, utiliser le java.util.simultanées pour plusieurs de thread au lieu de la mise en œuvre de votre propre. Un moyen simple est d'avoir un thread en attente pour les données, et de la poste à un autre thread pour traiter lorsqu'il y a suffisamment de données.
Alors maintenant, j'ai essayé votre solution. Malheureusement le même problème. Tout fonctionne bien, mais parfois, l'image n'est pas plus mis à jour après que j'ai changé tout seekBarValue. J'ai essayé quelques USB Débogage et maintenant j'ai cette Erreur: "OpenGLRenderer Ne peut pas générer une texture bitmap". Est-il possible que l'erreur est que mon image a moins de Pixels que l'ImageView? Je voulais android pour interpoler automatiquement. Mais il semble que je dois le faire sur mon propre. Ou est-il un autre problème. merci
Je ne suis pas sûr que le problème est. Une trace de la pile, ce serait bien. Et, aussi essayez de séparer les préoccupations en vous assurant de code fonctionne sans filetage code.
Je pense que j'ai résolu le problème. Je ne suis pas shure, mais je pense que l'app a voulu créer l'image Bitmap d'un Objet qui a été marquée par le GC pour les détruire. Si l'objet était toujours là mais n'a pas pu être utilisé pour mettre à jour l'Affichage. C'est pourquoi il n'y a pas de Message d'Erreur. Maintenant, je créer une nouvelle image de l'Objet à chaque boucle l'image Bitmap obtient calculé et il semble que cela fonctionne. Je vais prendre le AsyncTasak de la solution recommandée. Il est beaucoup plus facile à synchroniser. Donc, merci beaucoup. M'a beaucoup aidé!
OriginalL'auteur dongshengcn