2013-04-18 106 views
2

我遇到問題,找不到解決方案。當我通過藍牙連接接收數據時,我的程序突然崩潰。我正在單獨的線程中接收數據,其中每個字節都保存在隊列中。 我也有一個TimerTask,它調用每1毫秒從隊列中讀取數據的方法,並刷新UI中的TextBox。我的程序工作了一段時間,但後來突然崩潰。請幫忙。這裏是主要的代碼片段。Android:線程退出時未捕獲的異常

public class MainActivity extends Activity 
{  
    TextView myLabel1; 
    volatile boolean stopWorker = false; 


    public Queue<Byte> receiverQueue = new LinkedList<Byte>(); 
    protected byte[] receiverArray; 
    private boolean newDataRead = false; 

    //timer 
    TimerTask mTimerTask; 
    Timer timer = new Timer(); 
    final Handler timerHandler = new Handler(); 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 

super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 

myLabel1 = (TextView)findViewById(R.id.textView1); 
//start with timer ticking after 1 sec, and give timer tick every 1ms 

onTimerTick(); 
timer.schedule(mTimerTask, 1000, 1); 
} 


//method for reading data from receiverQueue 
protected void readDataFromReceiverBuffer() { 
    //if receiverQueue is not empty, read data 
    if(receiverQueue.isEmpty() == false) { 
     //declaration of byte array receiverField size of receiverQueue 
     receiverArray = new byte[receiverQueue.size()]; 
     //read bytes from queue until is empty 
      for (int i = 0; receiverQueue.isEmpty() == false; i++) { 
       //retrieves and removes the head of this queue, or returns null 
      receiverArray[i] = receiverQueue.poll(); 
      } 
     //variable newData is set to true, when we read new data from queue 
     newDataRead = true; 
    } 
}  


Thread dataReceiveThread = new Thread(new Runnable() { 
    //received byte 
    int receivedData; 
    public void run() { 
     while(!Thread.currentThread().isInterrupted() && !stopWorker) { 

      try { 
       //read one byte from InputStream 
       receivedData = mmInStream.read(); 
       //inserts received byte into this queue if it is possible 
       if(receivedData != -1) 
        receiverQueue.offer((byte)receivedData); 
      } 
      catch (IOException ex) { 
       stopWorker = true; 
      }   
      //Log.i(String.valueOf(receivedData), "valueOfReceivedData"); 
     }   
    }  
}); 

public void onTimerTick() { 
mTimerTask = new TimerTask() { 
    String temp; 
    //this method is called 
     public void run() { 
      //call method for read data from queue 
      readDataFromReceiverBuffer(); 
      timerHandler.post(new Runnable() { 
       public void run() { 
        //when new data has arrived, we update UI 
       if(newDataRead == true) { 
        //convert byte array to string 
        temp = new String(receiverArray, 0, receiverArray.length); 
        myLabel1.setText(temp); 
        newDataRead = false; 
       }        
        } 
       }); 
     }};  
}  

的logcat:

W/dalvikvm(12358): threadid=11: thread exiting with uncaught exception (group=0x40ab1210) 
E/AndroidRuntime(12358): FATAL EXCEPTION: Timer-0 
E/AndroidRuntime(12358): java.lang.ArrayIndexOutOfBoundsException: length=21; index=21 
E/AndroidRuntime(12358): at com.example.colibri2bb.MainActivity.readDataFromReceiverBuffer(MainActivity.java:195) 
E/AndroidRuntime(12358): at com.example.colibri2bb.MainActivity.readDataFromReceiverBuffer(MainActivity.java:195) 
E/AndroidRuntime(12358): at com.example.colibri2bb.MainActivity$3.run(MainActivity.java:230) 
E/AndroidRuntime(12358): at java.util.Timer$TimerImpl.run(Timer.java:284) 

的logcat:

W/dalvikvm(17344): threadid=12: thread exiting with uncaught exception (group=0x40ab1210) 
E/AndroidRuntime(17344): FATAL EXCEPTION: Timer-1 
E/AndroidRuntime(17344): java.util.NoSuchElementException 
E/AndroidRuntime(17344): atjava.util.LinkedList.removeFirstImpl(LinkedList.java:689) 
E/AndroidRuntime(17344): at java.util.LinkedList.removeFirst(LinkedList.java:676) 
E/AndroidRuntime(17344): at java.util.LinkedList.poll(LinkedList.java:895) 
E/AndroidRuntime(17344):atcom.example.colibri2bb.MainActivity.readDataFromReceiverBuffer(MainActivity.java:196) 
E/AndroidRuntime(17344): atcom.example.colibri2bb.MainActivity$3.run(MainActivity.java:231) 
E/AndroidRuntime(17344): at java.util.Timer$TimerImpl.run(Timer.java:284) 
+0

請發佈您的logcat – thepoosh 2013-04-18 07:14:12

+0

變量newDataRead應該被聲明爲volatile。 – Kishore 2013-04-18 07:21:18

+0

哪一行是195? – 2013-04-18 07:42:37

回答

0

其他線程可以修改receiverQueue並在讀取數據時添加數據嗎? 嘗試使用此循環代替。它應該確保你不會出界。

int queueSize = receiverQueue.size(); 
receiverArray = new byte[queueSize ]; 
for (int i = 0; i<queueSize; i++) { 
    ... 
} 
+0

謝謝。我認爲這可能是原因。這現在起作用,但我得到另一個錯誤。我發佈了新的LogCat。就像@ njzk2所說的,這可能是因爲任務太長而發生的? – anze87 2013-04-18 09:08:42

+0

現在看來,隊列中的元素比原來少...您可以在for循環中嘗試這兩種條件(隊列不是空的,而且我的大小)。但是這些都是小的修復,你有更多的線程更新同一個對象的問題。你需要同步所有這些線程。 – tbkn23 2013-04-18 09:58:19

+0

您能否給我建議什麼是同步所有線程的最佳方式?我很喜歡對象編程,並沒有太多的經驗。 – anze87 2013-04-18 11:23:35

0

這可能是因爲正被拋出的異常類型不是IOException異常。捕獲所有異常並查看 - 將IOException更改爲異常。

0

你的問題在這裏:java.lang.ArrayIndexOutOfBoundsException: length=21; index=21 MainActivity.readDataFromReceiverBuffer。 當數組只包含21個元素時,您嘗試將值分配給receiverArray[21]

0

receiverArray以隊列大小進行初始化,但隨後隊列在讀取時擴展,最終數據超出預期。

你必須確保你不被反對的大小測試指標(額外的數據將在readDataFromReceiverBuffer下一次執行讀取)讀太多了,最有可能的

你也可以指定一個更大的陣列(但測試仍然是必需的)

你的第二個問題可能是關於你的任務太長,因此有些重疊和併發訪問隊列。 (基本上,2個實例測試隊列是否爲空,都嘗試從中讀取,但只有一個元素)

我將使用帶循環的線程,循環執行的時間度量和睡眠延遲到下一個需要執行的時間,而不是一個計時器。這將確保讀取隊列的單一訪問權限。

相關問題