2013-04-18 1 views
2

문제가있어 해결책을 찾을 수 없습니다. 블루투스 연결을 통해 데이터를 수신하면 프로그램이 갑자기 작동하지 않습니다. 별도의 스레드에서 데이터를 수신하고 있습니다. 각 스레드는받은 바이트를 대기열에 저장합니다. 또한 1ms마다 큐에서 데이터를 읽는 메서드를 호출하는 TimerTask와 UI의 TextBox를 새로 고치는 TimerTask가 하나 있습니다. 내 프로그램은 잠시 동안 작동하지만 갑자기 충돌합니다. 도와주세요. 다음은 주요 코드 스 니펫입니다.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; 
       }        
        } 
       }); 
     }};  
}  

로그 캣 :

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) 

로그 캣 :

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

+0

변수 newDataRead가 volatile로 선언되어 있어야합니다. – Kishore

+0

어느 라인이 195입니까? –

답변

0

다른 스레드가 receiverQueue를 수정하고 읽는 동안 데이터를 추가 할 수 있습니까? for 루프를 대신 사용해보십시오. 당신이 경계를 벗어나지 않도록해야합니다.

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

고마워요. 나는 이것이 이유 일 수 있다고 생각한다. 이 지금은 작동하지만 다른 오류가 발생합니다. 새로운 LogCat을 게시합니다. @ njzk2가 말했듯이, 이것은 너무 긴 작업 때문에 일어날 수 있습니까? – anze87

+0

이제는 큐가 원래 가지고 있던 것보다 적은 요소가있는 것 같습니다 ... for 루프에서 두 조건을 모두 시도 할 수 있습니다 (큐가 비어 있지 않고 i <크기). 그러나 이것들은 모두 작은 수정 사항이며 동일한 객체를 업데이트하는 여러 스레드에 대한 더 큰 문제가 있습니다. 이 모든 스레드를 동기화해야합니다. – tbkn23

+0

모든 스레드를 동기화하는 가장 좋은 방법은 무엇입니까? 나는 객체 프로그래밍에 멍청하다. 많은 경험이 없다. – anze87

0

발생되고있는 예외 유형이 IOException이 아니기 때문에 그것은있을 수 있습니다. 모든 예외를 잡아보고 IOException을 Exception으로 변경합니다.

0

여기에 문제가 있습니다 : java.lang.ArrayIndexOutOfBoundsException: length=21; index=21 MainActivity.readDataFromReceiverBuffer. 배열에 21 개의 요소 만 포함되어있는 경우 값을 receiverArray[21]으로 지정하십시오!

0

receiverArray가 대기열의 크기로 초기화되었지만 읽는 동안 대기열이 확장되어 예상보다 많은 데이터로 끝납니다.

당신은 당신이 (추가 데이터가 readDataFromReceiverBuffer의 다음 실행에 읽히는) 크기에 대한 인덱스를 테스트하여 가장 가능성이, 너무 많이 읽고 있지 않은지은

당신은 또한 지정할 수있는 훨씬 더 큰 확인해야 배열 (하지만 테스트는 여전히 필수)

두 번째 문제는 작업이 너무 길어 큐에 일부 겹쳐서 동시에 액세스 할 수 있다는 것입니다. (기본적으로 큐가 비어있는 경우 두 인스턴스 테스트, 둘 다 읽으려고하지만 단 하나의 요소 만 있음)

루프가있는 스레드와 루프 실행 시간 측정 및 절전 타이머가 아닌 다음에 필요한 실행까지 지연됩니다. 그러면 대기열 읽기에 대한 단일 액세스가 보장됩니다.

관련 문제