2010-06-30 23 views
9

यहां मेरी स्थिति है: मैं एंड्रॉइड के लिए एक गेम बना रहा हूं और मेरी गेम की गतिविधि एक कस्टम सतह से बना है दृश्य जिसमें गेम तर्क और प्रतिपादन के लिए धागा है। आर्किटेक्चर Google की वेबसाइट से चंद्र लैंडर डेमो के समान है।गतिविधि को फिर से शुरू करते समय "थ्रेड पहले ही शुरू हो गया है"

जब गतिविधि यह SurfaceView बनाता है और इस प्रणाली को बुलाती है शुरू होता है:

@Override 
    public void surfaceCreated(SurfaceHolder holder) 
    { 
     renderThread.start(); 
    } 

जब मैं खेल, onPause() विधि कहा जाता है, जो surfaceDestroyed कॉल बाहर निकलने के लिए घर बटन दबाएँ()। सतह में घुमावदार मैं कॉल करके खेल थ्रेड को रोकता हूं:

@Override 
    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     synchronized(holder) 
     { 
      renderThread.stop(); 
     } 
    }  

ऐप पृष्ठभूमि ठीक हो जाता है। फिर, जब मैं आइकन दबाकर ऐप को फिर से लॉन्च करता हूं, तो मुझे स्क्रीन पर "बल बंद" पॉपअप के साथ लॉग में "थ्रेड पहले से शुरू हुआ" संदेश मिलता है। यह संदेश तब होता है जब गतिविधि "सतहक्रेटेड" विधि में प्रवेश करती है जब यह रेंडर थ्रेड पर प्रारंभ() को कॉल करती है।

अब मैंने इसे घंटों तक देखा है और यह नहीं पता कि यह क्यों है। मेरा मानना ​​है कि जब मैं ऐप बंद करता हूं तो मेरा धागा बंद हो जाता है इसलिए मुझे समझ में नहीं आता कि यह क्यों कहता है कि यह पहले ही शुरू हो चुका है।

उत्तर

8

वे विधियां ऐसा नहीं करतीं जो आपको लगता है कि वे करते हैं। API doc से:

यह एक धागा एक बार से अधिक शुरू करने के लिए कानूनी नहीं है।

और:

public final void stop() - पदावनत। यह विधि स्वाभाविक रूप से असुरक्षित है।

आप एक धागा रोकना चाहते हैं, तो आप धागा भीतर से Object.wait() और Objecft.notifyAll() उपयोग करना होगा।

+1

हाय, उत्तर के लिए धन्यवाद। मैंने थोड़ी देर में एक join() द्वारा स्टॉप() को प्रतिस्थापित किया। मेरा मानना ​​है कि यह धागे को रोकने से पहले इंतजार कर रहा है। लेकिन मुझे अभी भी एक ही समस्या है, क्या मुझे कुछ याद आ रही है? धागे की शुरुआत के लिए। मैं समझता हूं कि थ्रेड एक बार से अधिक त्रुटि संदेश शुरू नहीं किया जा सकता है। तो क्या आपको लगता है कि मुझे यह त्रुटि सिर्फ इसलिए मिलती है क्योंकि धागा ठीक से नहीं रोका गया है? धन्यवाद – NioX5199

+1

@ NioX5199: नहीं, शामिल हों() धागे को रोक नहीं देता है, यह इसके लिए खुद को खत्म करने की प्रतीक्षा करता है। आपको त्रुटि मिलती है क्योंकि थ्रेड पहले ही शुरू हो चुका है। थ्रेड * * को "बंद नहीं किया जा सकता" और पुनरारंभ नहीं किया जा सकता है। जैसा कि मैंने लिखा था: एक शर्त पूरी होने तक थ्रेड रोकने के लिए, आप ऑब्जेक्ट.वाइट() का उपयोग करते हैं। –

+0

वह शायद इस तरह से ऐसा नहीं करना चाहिए। धागे को पुनर्निर्माण शायद एक बेहतर दृष्टिकोण है। – alexanderblom

0

एक बुरा समाधान लेकिन यह काम करता है ..

public void surfaceCreated(SurfaceHolder holder) { 
     try{ 
     _thread.setRunning(true); 
     _thread.start(); 
     }catch(Exception ex){ 
      _thread = new TutorialThread(getHolder(), this); 
      _thread.start(); 
     } 

    } 

सुधार गरमी स्वागत कर रहे हैं।

+0

हालांकि यह काम करेगा (fsvo), आम तौर पर मुद्दों को पकड़ने और फिर कोशिश करने और सही करने के लिए यह एक अच्छा विचार नहीं है। इसके बजाय, * सक्रिय * हो और अपवादों को उनके अर्थ वापस दें। –

5

मेरी राय में आपको थ्रेड के उप-वर्ग में अपना कोड पैक नहीं करना चाहिए यदि आप अक्सर थ्रेड को शुरू करना और रोकना चाहते हैं (उदाहरण ऐसा करते हैं क्योंकि यह कोड को छोटा बनाता है)। इसके बजाए एक रननेबल का प्रयोग करें। जब आप चाहें तो पुराने थ्रेड को रोक और त्याग सकते हैं और जब आप इसे फिर से शुरू करने की आवश्यकता होती है तो रननेबल को निष्पादित करने के लिए एक नई थ्रेड ऑब्जेक्ट बनाएं।

private TutorialRunnable tutorialRunnable; 

... 

// Synchronization and error checking omitted for brevity. 
public void surfaceCreated(SurfaceHolder holder) { 
    thread = new Thread(tutorialRunnable); 
    thread.start(); 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    tutorialRunnable.setRunning(false); 
    while (thread != null) { 
     try { 
      thread.join(); 
      thread = null; 
     } catch (InterruptedException e) { 
     } 
    } 
} 

इसके अलावा, अपवादों पर भरोसा करना खराब रूप है। इसका उपयोग अंतिम उपाय के रूप में किया जाना चाहिए जब आपका स्वयं का कोड अप्रत्याशित रूप से व्यवहार करता है।

संबंधित मुद्दे

 संबंधित मुद्दे