簡體   English   中英

Android:線程未捕獲而退出

[英]Android: thread exiting with uncaught exception

我有問題,但找不到解決方案。 通過藍牙連接接收數據時,程序突然崩潰。 我在單獨的線程中接收數據,每個接收到的字節都保存在隊列中。 我還有一個TimerTask,它每隔1毫秒調用一次從隊列讀取數據的方法,並刷新UI中的TextBox。 我的程序工作了一段時間,但隨后突然崩潰。 請幫忙。 以下是主要的代碼片段。

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)

可能是因為拋出的Exception類型不是IOException。 捕獲所有異常,然后查看-將IOException更改為Exception。

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

您的receiverArray會使用隊列的大小進行初始化,但是當您讀取隊列時,隊列會擴展,最終您將得到比預期更多的數據。

您必須確保沒有讀取太多,最有可能的是通過針對大小測試索引(額外的數據將在下一次執行readDataFromReceiverBuffer )。

您也可以分配更大的數組(但仍然必須進行測試)

第二個問題可能是您的任務太長,因此對隊列有一些重疊和並發的訪問。 (基本上,有2個實例測試隊列是否為空,都嘗試讀取該隊列,但是只有一個元素)

我將使用具有循環的線程,循環執行的時間度量以及用於延遲到下一個需要執行的時間的睡眠,而不是使用計時器。 這樣可以確保對讀取隊列的單一訪問。

其他一些線程可以在您從接收器隊列中讀取數據時對其進行修改並添加數據嗎? 請嘗試使用此for循環。 它應該確保您不會超出范圍。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM