2012-02-03 36 views
1

我有一個線程"reader",它讀取一個文件並更新列表A.另一個線程"drawer"讀取變量a中的內容,執行某些操作,調用ondraw,然後休眠500ms(在此期間,讀者填充A)。Android - 如何在另一個活動期間暫停線程?

我也有一個首選活動,如果我按菜單按鈕開始。

的問題是,如果我按按鈕的同時讀線程還沒有完成閱讀他的文件,我有恩於logcat的錯誤。(見下文)

我已經看到了這個問題的讀者當它向我顯示首選項菜單時正在運行的線程,事實上,如果我等到讀者結束,並且我點擊了一個首選項,它一切順利,但是如果我單擊它的運行igot時發生錯誤。

如何處理當我重新啓動時仍在運行的線程?我如何"pause"他們?成爲我的文件閱讀可以很長,所以我不能等待讀者線程結束。

感謝

編輯:爲了更精確,什麼appens的是,如果我按菜單鍵,preferenceActivity開始,我看到正確的視圖(單選按鈕等),但問題是,當我點擊在屏幕上的隨機點上,它給我錯誤。如果我等那麼讀thred結束(我看到它的logcat),然後我點擊ARANDOM點,它會everithing好...

logcat的錯誤:

02-03 10:18:51.196: ERROR/ActivityManager(66): ANR in it.planningpathapp.ale (it.planningpathapp.ale/.Preferences) 
02-03 10:18:51.196: ERROR/ActivityManager(66): Reason: keyDispatchingTimedOut 
02-03 10:18:51.196: ERROR/ActivityManager(66): Load: 0.7/0.29/0.29 
02-03 10:18:51.196: ERROR/ActivityManager(66): CPU usage from 13441ms to 36ms ago: 
02-03 10:18:51.196: ERROR/ActivityManager(66): ningpathapp.ale: 82% = 75% user + 7% kernel/faults: 6211 minor 1 major 
02-03 10:18:51.196: ERROR/ActivityManager(66): adbd: 16% = 0% user + 15% kernel/faults: 36 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): system_server: 11% = 8% user + 3% kernel/faults: 229 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): logcat: 3% = 1% user + 2% kernel 
02-03 10:18:51.196: ERROR/ActivityManager(66): m.android.phone: 0% = 0% user + 0% kernel/faults: 33 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): ronsoft.openwnn: 0% = 0% user + 0% kernel/faults: 30 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): m.android.music: 0% = 0% user + 0% kernel/faults: 52 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): id.defcontainer: 0% = 0% user + 0% kernel/faults: 14 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): com.svox.pico: 0% = 0% user + 0% kernel/faults: 15 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): ndroid.launcher: 0% = 0% user + 0% kernel/faults: 18 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): com.android.mms: 0% = 0% user + 0% kernel/faults: 22 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): m.android.email: 0% = 0% user + 0% kernel/faults: 41 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): android.protips: 0% = 0% user + 0% kernel/faults: 15 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): .quicksearchbox: 0% = 0% user + 0% kernel/faults: 34 minor 
02-03 10:18:51.196: ERROR/ActivityManager(66): TOTAL: 99% = 72% user + 20% kernel + 1% irq + 6% softirq 
02-03 10:18:51.216: WARN/WindowManager(66): No window to dispatch pointer action 1 
public class PathPlanningApp1Activity extends Activity { 


private static Object lock=new Object(); 

//Mie tag per il debug mediante LogCat 
private static final String TAG_readFile = "READFILE_thread"; 
private static final String TAG_draw = "DRAW_Thread"; 
private static final String TAG_error = "ERROR"; 

private final HashMap < Integer , vertex > map = new HashMap < Integer , vertex>(); 
private final LinkedList <vertex> originalPath = new LinkedList <vertex>(); 
private final LinkedList <vertex> originale = new LinkedList <vertex>(); 
private final ArrayList <vertex> obstacles = new ArrayList<vertex>(); 
private final ArrayList <vertex> obstacles_notordered = new ArrayList<vertex>(); 


private int mapWidth=1; 
private int mapHeight=1; 

Panel panel; 
Resources res; 

private Bitmap mBitmap; 
private Bitmap obstaclesBmp=Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888); 

private float zoom=15; 


/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    res= this.getResources() ; 
    panel=new Panel(this); 
    setContentView(panel); 
    Log.d(getLocalClassName(), "ON CREATE"); 

} 
public boolean onCreateOptionsMenu(Menu menu) { 
    MenuInflater inflater = getMenuInflater(); 
    inflater.inflate(R.menu.menu, menu); 
    return true; 
} 
protected void onResume() 
{Log.d(getLocalClassName(), "ON RESUME"); 
    setContentView(panel); 

    super.onResume(); 

} 
protected void onDestroy(){ 
    Log.d(getLocalClassName(), "ON DESTROY"); 
    super.onDestroy(); 
} 
protected void onPause(){ 
    Log.d(getLocalClassName(), "ON PAUSE"); 
    Log.d(getLocalClassName(), "stato drawer" +panel.drawerThread.getState()); 
    Log.d(getLocalClassName(), "stato frt" +panel.frt.getState()); 

    super.onPause(); 
} 
@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
     case R.id.ic_launcher:  Toast.makeText(this, "You pressed the icon!", Toast.LENGTH_LONG).show(); 
            Intent settingsActivity = new Intent(this,Preferences.class); 
            startActivity(settingsActivity); 
          break; 
     case R.id.text:  Toast.makeText(this, "You pressed the text!", Toast.LENGTH_LONG).show(); 
          break; 
     case R.id.icontext: Toast.makeText(this, "You pressed the icon and text!", Toast.LENGTH_LONG).show(); 
          break; 
    } 
    return true; 
} 



class Panel extends SurfaceView implements SurfaceHolder.Callback{ 

    FileReaderThread frt=new FileReaderThread(); 
    DrawerThread drawerThread ; 

    public Panel(Context context) { 
     super(context); 

     getHolder().addCallback(this); 
     drawerThread = new DrawerThread(getHolder() , this); 
     setDrawingCacheEnabled(true); 
     setFocusable(true); 

    } 

    public void onDraw(Canvas canvas) { 
     canvas.drawColor(Color.BLACK); 
     try{ 


     int i=0; 

     int height=canvas.getHeight(); 
     int width=canvas.getWidth(); 
     Paint paint = new Paint(); 

     paint.setColor(Color.GREEN); 


     //Log.d(TAG_draw, " obstaclesBmp="+obstaclesBmp.getHeight()); 
     if (obstaclesBmp != null){ 
      synchronized(obstaclesBmp){ 

       canvas.drawBitmap(obstaclesBmp, 0, 0, null); 

      } 
     } 


     }catch(OutOfMemoryError e){ 
      Log.e(TAG_error, "ONDRAW !!Bitmap troppo grossa !dim:"+mapWidth+" "+mapHeight); 
     } 

     } 

    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
     // TODO Auto-generated method stub 

    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     // TODO Auto-generated method stub 

     if(frt.getState()== Thread.State.TERMINATED){ 
      //frt = new FileReaderThread();     
       //  frt.start(); 
     // <-- added fix 
      }else { 
       Log.d(TAG_readFile," stato frt "+frt.getState()); 
       frt.setRunning(true); 
       frt.start(); 
      } 

     if(drawerThread.getState()==Thread.State.TERMINATED){ 
      drawerThread = new DrawerThread(getHolder() , this); 
      drawerThread.setRunning(true); 
      drawerThread.start(); 
     } 
     else{ 
      drawerThread.setRunning(true); 
      drawerThread.start(); 
     } 



    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // TODO Auto-generated method stub 
     boolean retry = true; 
     drawerThread.setRunning(false); 
     while (retry) { 
      try { 
       drawerThread.join(); 
       retry = false; 
      } catch (InterruptedException e) { 
       // we will try it again and again... 
      } 
     } 
     retry = true; 
     frt.setRunning(false); 
     while (retry) { 
      try { 
       frt.join(); 
       retry = false; 
      } catch (InterruptedException e) { 
       // we will try it again and again... 
      } 
     } 

    } 

} 

public class DrawerThread extends Thread { 
    private SurfaceHolder _surfaceHolder; 
    private Panel _panel; 
    private boolean _run = false; 
    Bitmap oldbmp=null; 
    Bitmap newbmp=null; 
    Bitmap obstaclesBmpTmp = null; 

    int i=0; 
    int lasti=0; 
    int oldW=-1,oldH=-1; 

    public DrawerThread(SurfaceHolder surfaceHolder, Panel panel) { 
     _surfaceHolder = surfaceHolder; 
     _panel = panel; 
    } 

    public void setRunning(boolean run) { 
     _run = run; 
    } 

    public SurfaceHolder getSurfaceHolder() { 
     return _surfaceHolder; 
    } 
    public void UpdateBmp(){ 
     Log.d(TAG_draw, "Update!"); 
     try{ 
     int provazoom=7; 
     Paint paint = new Paint(); 
     int mymapWidth=mapWidth; 
     int mymapHeight=mapHeight; 


      if(mymapWidth>oldW || mymapHeight>oldH ||oldW<0 || oldH<0){ 

       obstaclesBmpTmp=Bitmap.createBitmap(mymapWidth*provazoom,mymapHeight*provazoom, Bitmap.Config.ARGB_4444); 
       lasti=0; 

       Log.d(TAG_draw, "Cambiate dimensioni! "+oldW+" contro "+mymapWidth+" e "+oldH+" contro"+mymapHeight); 
       oldW=mymapWidth; 
       oldH=mymapHeight; 

      } 
      else{ 
       Log.d(TAG_draw, "Dimensioni uguali! "); 

      } 
      Log.d(TAG_draw, "parto dall'index "+lasti); 

      Canvas tmpCanvas=new Canvas(obstaclesBmpTmp);    
      //tmpCanvas.drawColor(Color.DKGRAY); 

      paint.setColor(Color.WHITE); 
      int corrx=-20; 
      int corry=10; 
      for(i=lasti;i<obstacles_notordered.size();i++){ 

        float x=(float)( ((obstacles_notordered.get(i).x) +mymapWidth/2 )*provazoom +corrx ); 
        float y=(float)( ((-1*obstacles_notordered.get(i).y) +mymapHeight/2 )*provazoom +corry ); 

        //Log.d(TAG_readFile, "trasformo : "+obstacles.get(i).x+" e "+obstacles.get(i).y+" in "+x+" "+(-1*obstacles.get(i).y)+"con map w e h"+mapWidth+" "+mapHeight); 
        //Log.d(TAG_draw, "x e y "+x+" "+y); 
        tmpCanvas.drawPoint(x,y, paint);        
        Paint prova=new Paint(); 
        prova.setColor(Color.WHITE); 
        lasti=i; 
        //tmpCanvas.drawCircle(x, y, (float)1, prova); 
       } 

     synchronized(obstaclesBmp){ 

      obstaclesBmp=Bitmap.createBitmap(obstaclesBmpTmp); 

     } 
     }catch(OutOfMemoryError e){ 
      Log.e(TAG_error, "Bitmap troppo grossa !dim:"+mapWidth+" "+mapHeight); 
     } 

    } 

    @Override 
    public void run() { 
     Log.d(TAG_draw, "Drawer Thread Partito"); 
     Canvas c; 
     while (_run) { 
      c = null; 
      try { 
       c = _surfaceHolder.lockCanvas(null); 
       synchronized (_surfaceHolder) { 
        //Log.d(TAG_draw, "Drawer Thread chiama onDraw"); 

        //Log.d(TAG_draw, "Drawer Thread ha il lock !"); 
        UpdateBmp(); 
        _panel.onDraw(c); 
        Log.d(TAG_draw, "Drawer Thread Dorme"); 
        sleep(500); 
        Log.d(TAG_draw, "Drawer Thread Sveglio"); 

       } 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } finally { 
       // do this in a finally so that if an exception is thrown 
       // during the above, we don't leave the Surface in an 
       // inconsistent state 
       if (c != null) { 
        _surfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 
     //Log.d(TAG_draw, "Drawer Thread termina"); 

    } 


} 

public class FileReaderThread extends Thread { 
    private boolean _run = false; 
    public void setRunning(boolean run) { 
     _run = run; 
    } 

    public double modulo (vertex v){ 
     return Math.sqrt(Math.pow(v.x,2)+Math.pow(v.y,2)) ; 

    } 
    public void insord(vertex dains,LinkedList<vertex> lista){ 
     //funzione per l'inserimento ordinato in una lista 
     ListIterator<vertex> i2=lista.listIterator(); 

     if(lista.size()==0){ 
      lista.add(dains);   

     } 
     else{ 
      while(i2.hasNext()){  

       vertex temp=i2.next(); 

       //System.out.println("x da ins "+dains.x+" confrontata con "+temp.x); 
       //if(modulo(temp)==modulo(dains)&& temp.x==dains.x && temp.y==dains.y){ } 
       if(modulo(temp)>=modulo(dains)){ 
        lista.add(i2.previousIndex(), dains); 
        //System.out.println("inserito in posizione "+(i2.previousIndex())); 
        break; 
       } 
       if(i2.hasNext()==false){ 
        lista.addLast(dains);   
        //System.out.println("inserito in ultima posizione "+(i2.previousIndex()+1)); 
        break; 

       }  
      } 
     } 
    } 
    public void insord_x(vertex dains,ArrayList<vertex> lista){ 
     //inserimento ordinato rispetto alle x per gli ostacoli 
     ListIterator<vertex> i2=lista.listIterator(); 

     if(lista.size()==0){ 
      lista.add(dains);   

     } 
     else{ 
      while(i2.hasNext()){  

       vertex temp=i2.next(); 

       //System.out.println("x da ins "+dains.x+" confrontata con "+temp.x); 
       //if(modulo(temp)==modulo(dains)&& temp.x==dains.x && temp.y==dains.y){ } 
       if(temp.x>=dains.x){ 
        lista.add(i2.previousIndex(), dains); 
        //System.out.println("inserito in posizione "+(i2.previousIndex())); 
        break; 
       } 
       if(i2.hasNext()==false){ 
        lista.add(i2.nextIndex(),dains);    
        //System.out.println("inserito in ultima posizione "+(i2.previousIndex()+1)); 
        break; 

       }  
      } 
     } 
    } 


    public void run(){ 
     while (_run) { 
      Log.d(TAG_readFile, "Reader Thread Partito"); 

      //istanzio un oggetto di tipo Resources per usare facilmente le mie risorse dalla cartella Res 
      //Resources res = this.getResources() ; 

      //Recupero dalla cartella res\raw il file sottoforma di stream e lo trasformo 

      File sdcard = Environment.getExternalStorageDirectory(); 

      //Get the text file 
      File file = new File(sdcard,"provatesto.g2o"); 


      InputStream in = null; 
      try { 
       in = new BufferedInputStream(new FileInputStream(file)); 
       Log.d(TAG_readFile, "nome file "+file.getName()); 
      } catch (FileNotFoundException e) { 
       // TODO Auto-generated catch block 
       Log.d(TAG_readFile, "FILE NON TROVATOOOOOOOO"); 
       e.printStackTrace(); 
      } 

      //InputStream instream = res.openRawResource(R.raw.provatesto);   
      //DataInputStream dis = new DataInputStream(instream); 
      DataInputStream dis = new DataInputStream(in); 
      String line= "empty"; 
      int vIndex = 0; 
      int oIndex = 0; 

      //leggo una linea 


      try { 
       //Log.d(TAG_readFile, "leggo il file"); 

       while((line = dis.readLine()) != null){ 
        //Log.d(TAG_readFile, "Reader Thread ha il lock!!"); 
        //Log.d(TAG_readFile, "Ho letto la linea: "+line); 
        StringTokenizer st= new StringTokenizer(line); 
        //Log.d(TAG_readFile, "Ho letto la linea: "+line); 

        try{ 
         String entry=st.nextToken(); 
         //Log.d(TAG_readFile, "Token: "+entry); 
         if(entry.equals("VERTEX_SE2")){ 
          Integer index = Integer.parseInt(st.nextToken()); 
          Double x = Double.parseDouble(st.nextToken()); 
          Double y = Double.parseDouble(st.nextToken()); 
          Double r = Double.parseDouble(st.nextToken()); 

          vertex newVertex=new vertex(x,y,vIndex); 
          synchronized(map){ 
           map.put(vIndex, newVertex); 
          } 
          synchronized(originale){ 
           originale.add(newVertex); 
          } 

          if(vIndex>0) map.get(vIndex-1).addEdge(map.get(vIndex)); 

          insord(newVertex,originalPath); 
          //Log.d(TAG_readFile, ""+vIndex); 

          vIndex++; 

         } 
         else if(entry.equals("VERTEX_XY")){ 

          Integer index = Integer.parseInt(st.nextToken()); 
          Double x = Double.parseDouble(st.nextToken()); 
          Double y = Double.parseDouble(st.nextToken()); 
          //Log.d(TAG_readFile, "xy index: "+x+" "+y); 
          try{       
           vertex newVertex=obstacles.get(index); 
          }catch(IndexOutOfBoundsException e){ 
           //obstacles.add(new vertex(Double.parseDouble(x),Double.parseDouble(y),Integer.parseInt(index))); 

           if(Math.abs(x)>mapWidth/2) mapWidth=(int)Math.ceil(Math.abs(x))*2; 

           if(Math.abs(y)>mapHeight/2) mapHeight=(int)Math.ceil(Math.abs(y)*2); 

           //Log.d(TAG_readFile, "mapWidth "+mapWidth+" mapHeight "+mapHeight); 
           /* 
           synchronized(obstacles){ 
            insord_x(new vertex(x,y,index),obstacles); 
           } 
           */ 
           synchronized(obstacles){ 
            obstacles_notordered.add((new vertex(x,y,index))); 
           } 


          } 

          oIndex++; 
         } 
         else {//Log.d(TAG_readFile, "edge"); 

         } 
         if(oIndex%200==0){ 
          Log.d(TAG_readFile, "Reader thread sta girando"); 
         } 

        }catch(NoSuchElementException e){ 

        } 



        //Log.d(TAG_readFile, "oindex "+oIndex); 



       }// 



      } catch (IOException e) { 
       Log.e(TAG_readFile, "Errore durante la lettura di una linea."); 
       line= "end"; 
       e.printStackTrace(); 
      } 

      Log.d(TAG_readFile, "Reader Thread Termina"); 
     }} 



} 

} 

回答

0

要調用的onDraw我猜你是在你的UI線程中,但它也表示你在這個線程中睡覺。這對於響應能力非常不利。看起來你的UI線程被鎖定並且超時。確保你在UI線程以外的線程上進行任何處理/休眠。

您不能完全暫停您的線程,但您可以使用等待/通知條件暫停線程,直到滿足條件。

Here是等待/通知給你一個想法的快速教程。

+0

謝謝!我試過使用等待/通知,但如果我讓線程在等待條件,我開始preferenceActivity它給了我同樣的錯誤。 爲更具體我使用「lunarlander」的想法..所以我有一個擴展sufraceview和實現surface holder.callback和內部,我創建我的線程,抽屜線程調用面板的面板類。onDraw() – Dedanan 2012-02-03 11:03:24

+0

好吧,我需要看你的代碼進一步評論。添加代碼 – mcnicholls 2012-02-03 11:14:03

+0

,感謝您的幫助。 – Dedanan 2012-02-03 11:27:00

1

你也不應該在你的UI線程中做任何長期的處理,因爲它可能會阻止它,並給你ANR異常。由於無法從另一個線程更新UI,因此通常使用帶有ThreadAsyncTaskHandler在後臺運行長期進程並更新UI線程。

查看painless threading的一些解釋,並在android performance一個很好的教程在這一個。

+0

謝謝! ithink我這樣做是因爲我的onDraw函數oly繪製一個位圖。該位圖是在drawer中生成的Thread在他的run()函數中執行的: \t UpdateBmp(); //更新公共bmp \t _panel.onDraw(c); \t \t sleep(500); } – Dedanan 2012-02-03 11:19:34

0

我不會使用兩個單獨的線程。事實上,當文件中的某些內容發生變化時,您只需要重新繪製,因此您可以從後臺線程調用postInvalidate(),並且這將在UI線程上調用draw()