2011-01-04 7 views
5

के साथ डीबगिंग मैं अक्सर SwingUtilities.invokeLater() का उपयोग करता हूं। ऐसा करने से, हालांकि, कुछ मामलों में डीबग करना मुश्किल हो जाता है: आप SwingUtilities.invokeLater() नामक कोड के स्टैक ट्रेस को नहीं देख सकते हैं, क्योंकि उस कोड ने पहले से ही इसे निष्पादित कर दिया है।जावा: SwingUtilities.invokeLater()

क्या SwingUtilities.invokeLater() पर कॉल करते समय कुछ प्रकार के संदर्भ (केवल डीबगिंग उद्देश्यों के लिए) सेट करने के लिए कोई सुझाव हैं, ताकि आप यह पता लगा सकें कि यूआई घटना के सवाल के कारण क्या हुआ?

+1

आप किसी भी स्वीकार्य समाधान मिला: invokeLater अन्य invokeLater से कहा जा सकता है जब फिर पाठ postEvent 9 from 7 लॉग

 // Place this code somewhere in the main class to override queue EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); eventQueue.push(new MyEventQueue()); 

कहाँ वर्ग MyEventQueue ऐसा दिखाई दे सकता में मुद्रित किया जाना चाहते हैं?वास्तव में यह जानने में दिलचस्पी है कि आपने आखिरकार क्या किया :) – Twister

उत्तर

1

विधि को ओवरराइड करें, एक लॉग कॉल जोड़ें और फिर असली कॉल करें ... चेतावनी: आपको अपनी सभी कॉल मूल विधि में बदलना होगा।

आप रननेबल को भी लपेट सकते हैं और एक संदर्भ संख्या जोड़ सकते हैं (उदाहरण के लिए बाद में कॉल करने के लिए कॉल का टाइमस्टैम्प)। runnable शुरू होता है यह संदर्भ संख्या मुद्रित करने के लिए शुरू किया

public static void myInvokeLater(final Runnable runnable) { 
    long ts = System.currentTimeMillis(); 
    Log.info("call to invoke later, context :" + ts); 
    Runnable r = new Runnable() { 
      public void run() { 
       Log.info("start runnable of invokeLater with context :" + ts); 
       runnable.run(); 
      } 
     }; 
    SwingUtilities.invokeLater(r); 
} 
+0

यदि आप System.out.println (runnable) और System.out.println (यह) रननेबल के रन विधि के भीतर हैं, तो आप उन्हें मिलान करने में सक्षम होना चाहिए :) –

+0

नहीं System.out.println कृपया! –

+0

और आसानी से निष्क्रिय नहीं है। वहां आप बस जोड़ सकते हैं अगर (DEBUG) फिर जादू करें, अन्यथा केवल असली InvokeLater के लिए आगे बढ़ें। – Twister

1

मैं एक और अधिक उन्नत एक, हो सकता है कुछ "localUtilities" में एम्बेडेड, जो करने के लिए आप दे दोनों से "मानक" swingUtilites # invokeLater विधि को बदलने के लिए जाते हैं एक तर्क के रूप में निष्पादित करने के लिए कोड, स्रोत घटना या इसकी एक थ्रेड-सुरक्षित प्रति (मुझे लगता है कि आपके पास एक स्रोत ईवेंट है, जो भी इसका प्रकार है)।

1

यदि आप अक्सर invokeLater पर कॉल कर रहे हैं, तो आप अपने थ्रेडिंग को सरल बनाने पर विचार करना चाहेंगे।

invokeLater प्रभावी रूप से उत्परिवर्तनीय सांख्यिकी का उपयोग कर रहा है और इसलिए शुद्ध बुराई है। यदि आप invokeLater और isDispatchThread के साथ इंटरफेस का उपयोग करने के लिए EventQueue.invokeLater पर कॉल करने से स्विच करते हैं तो परीक्षण और अधिक आसान हो जाएगा।

यह दुर्भाग्यपूर्ण है कि आप सामान्य रूप से invokeLater और isDispatchThread पुस्तकालयों द्वारा उपयोग नहीं कर सकते हैं।

+0

क्या आप "म्यूटेबल स्टेटिक्स" के बारे में अपनी टिप्पणी समझा सकते हैं? मुझे कोई कारण नहीं दिख रहा है कि आपको यूआई/गैर-यूआई सीमा में म्यूटेबल डेटा पास करने की आवश्यकता क्यों है। – Anon

+0

@Anon स्थिर 'invokeLater' के कार्यान्वयन को लाइन के साथ कहीं भी [mutable] स्थिर ईवेंट कतार चुनना होगा। –

+0

तो आप एक स्थिर (इंजेक्शन योग्य) उदाहरण के साथ स्थिर कॉल को 'स्विंग यूटिलिटीज' में बदलने का सुझाव दे रहे हैं? – Anon

2

यहां अन्य अधिकांश उत्तर अच्छे हैं, लेकिन मैं एक और सुझाव जोड़ना चाहता हूं। यदि आप बहुत बार SwingUtilities.invokeLater को कॉल कर रहे हैं, तो संभवतः आप इसे कुछ समय तक अनावश्यक रूप से कर रहे हैं, खासकर यदि कॉल का एकमात्र उद्देश्य यह सुनिश्चित करना है कि ईवेंट थ्रेड पर स्विंग परिवर्तन किए जाएं। इस जब उचित प्रयास करें:

if (SwingUtilities.isEventDispatchThread()) { 
    myRunnable.run(); 
} else { 
    SwingUtilities.invokeLater(myRunnable); 
} 
+0

तो स्विंग यूटिलिटीज पहले से ही अपने invokeLater() कार्यान्वयन के हिस्से के रूप में ऐसा नहीं करता है? –

+0

नहीं, क्योंकि सभी लंबित घटनाओं को संसाधित करने के बाद, केवल इन्हें 'बाद में' निष्पादित करता है। जाहिर है अगर आपको उस व्यवहार की ज़रूरत है तो आप इस चाल का उपयोग नहीं कर सकते हैं। invokeAndWait भी एक विकल्प के रूप में काम कर सकते हैं। – DJClayworth

1

आप invokeLater() के लिए अनाम Runnable रों गुजर रहे हैं?

यदि हां, तो मैं उन्हें गैर-अज्ञात कक्षाओं के साथ बदलने का सुझाव दूंगा, जो कोड की कुछ पंक्तियां जोड़ देगा, लेकिन आपको कम से कम कुछ स्तर की ट्रेसिबिलिटी (उदाहरण: TableUpdateFromQuery) देगी। यदि आप ऐप में केवल एक ही स्थान से किसी विशेष प्रकार के अपडेट का आह्वान करते हैं तो यह सबसे अच्छा काम करता है। यह आपको "पृष्ठभूमि गतिविधियों" के मार्ग से भी नीचे ले जाता है, जिसे यूआई के बाहर परीक्षण किया जा सकता है।

2

आप EventQueue ओवरराइड करने और पोस्ट की गई घटनाओं के लिए स्टैकट्रैक प्रिंट करने का प्रयास कर सकते हैं। इसके अलावा नीचे दिए गए उदाहरण में प्रत्येक पोस्ट किए गए ईवेंट को एक अद्वितीय संख्या असाइन की जाएगी।

import java.awt.AWTEvent; 
import java.awt.EventQueue; 
import java.awt.event.InvocationEvent; 
import java.util.WeakHashMap; 

public class MyEventQueue extends EventQueue { 

    int currentNumber = 0; 
    WeakHashMap<AWTEvent,Integer> eventIdMap = new WeakHashMap<AWTEvent,Integer>(); 
    AWTEvent currentEvent = null; 

    protected void dispatchEvent(AWTEvent event) { 
     if (event instanceof InvocationEvent) { 
      currentEvent = event; 
     } 
     super.dispatchEvent(event); 
     currentEvent = null; 
    } 

    public void postEvent(AWTEvent event) { 
     if (event instanceof InvocationEvent) { 
      currentNumber = currentNumber + 1; 
      eventIdMap.put(event, currentNumber); 
      System.out.println("postEvent " + currentNumber + " " + 
        (currentEvent != null ? "from " + eventIdMap.get(currentEvent) : "")); 
      for(StackTraceElement element : new RuntimeException().getStackTrace()) { 
       System.out.println("\t" + element); 
      } 
     } 
     super.postEvent(event); 
    } 
} 
+0

एक स्पष्टीकरण के रूप में, एक 'EventQueue' बढ़ाता है और वांछित विधि को ओवरराइड करता है, उदा। 'InvokeLater()'। यहां एक संबंधित उदाहरण है, http://stackoverflow.com/questions/3158409 – trashgod

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