2010-11-19 12 views
5

मेरे पास यह ActionListener है जिसे ईडीटी में बुलाया जाता है। मेरा साजिश() फ़ंक्शन कम्प्यूटेशनल रूप से भारी है, यह आसानी से पांच सेकंड ले सकता है। इसने जीयूआई को उम्मीद के रूप में लटका दिया। मैंने SwingUtilities.invokeLater कोड जोड़ा और यह अभी भी लटकता है। क्या जीयूआई अब उत्तरदायी नहीं होना चाहिए कि मैं अपने हेव गणना के लिए एक अलग धागा पैदा कर रहा हूं?SwingUtilities.invokeLater का उपयोग करने के बाद भी मेरा जीयूआई अभी भी क्यों लटका है?

final ActionListener applyListener = new ActionListener() 
     { 
      @CommitingFunction 
      public void actionPerformed(ActionEvent arg0) 
      { 
       /*Don't do plotting in the EDT :)*/ 
       SwingUtilities.invokeLater(new Runnable() 
       { 
        public void run() 
        { 
         plot(); 
        } 
       }); 
      } 
     }; 

उत्तर

15

बिलकुल नहीं। InvokeLater एक नया धागा नहीं बना रहा है। invokeLater exists to tell Swing explicitly "use the Event Dispatching Thread for this, but not right now". आक्रमण और आह्वान करने के लिए मौजूद है, जो आपको उन कार्यों को करने के लिए मौजूद है जो अन्य धागे से इवेंट डिस्पैचिंग थ्रेड के लिए केवल सुरक्षित हैं- उन धागे पर नहीं कर रहे हैं, लेकिन ईडीटी को उन्हें करने के लिए कहकर।

आपका एक्शनलिस्टर स्विंग की घटना प्रेषण कतार पर रननेबल फेंकने, बहुत तेज़ी से भाग जाएगा। फिर जब यह दूर हो जाता है, तो साजिश चलाने के लिए इसमें पांच सेकंड लगेंगे()।

साजिश() को दोबारा करने का एकमात्र कामकाज है। SwingWorker (या समान मल्टीथ्रेडिंग रणनीति का उपयोग करें, लेकिन स्विंगवर्कर शायद इसके लिए सबसे अच्छा है) वास्तव में प्लॉट() को एक अलग थ्रेड पर तर्क देने के लिए। वह थ्रेड सुरक्षित रूप से कुछ भी नहीं खींच सकता है क्योंकि यह स्विंग इवेंट डिस्पैचिंग थ्रेड नहीं है, इसलिए इसके सभी ड्रॉ ऑपरेशंस को invokeLater() के माध्यम से करने की आवश्यकता है। दक्षता कारणों से, आपको अपनी गणना से संग्रहीत परिणामों का उपयोग करके, एक invokeLater() पर, एक ही समय में सभी ड्राइंग ऑपरेशन करने का प्रयास करना चाहिए।

+1

चल (अन्यथा आप लगातार रिबूट कर देंगे। इसलिए मैं एक वर्ग है कि फैली में भूखंड() कोड को चलाने के लिए करना चाहते हैं SwingWorker, और doInBackground() फ़ंक्शन में उस संगणकीय रूप से भारी कोड चलाएं और फिर मेरे प्रदर्शन को रीफ्रेश करने के लिए किए गए() फ़ंक्शन का उपयोग करें? क्या गणना के दौरान मेरा जीयूआई अभी भी सक्रिय होगा? – smuggledPancakes

+0

@ user464095: हाँ, बिल्कुल। – ColinD

+1

बिंगो। स्विंगवर्कर ऐसा करता है और इसके लिए है। –

1

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

मेरा सुझाव है कि आप एक निष्पादक सेवा का उपयोग करने के लिए देखें।

जैसा कि @ एडम सुझाव देता है, किसी भी वास्तविक ड्राइंग को इनवॉकलेटर के माध्यम से किया जाना आवश्यक है।

1

आप प्लॉट() फ़ंक्शन के अंदर क्या नहीं दिखाते हैं, लेकिन आपको पर कोई चित्र नहीं डालना चाहिए। नए धागे में जो कुछ भी आप चाहते हैं उसकी गणना करें, और ईडीटी में पेंटिंग करें। ऐसा करने के लिए, SwingWorker

3

का उपयोग करना बेहतर है, आप जो भी सोचते हैं उसके विपरीत आप कर रहे हैं। ईडीटी के बाहर अपना गणना धागा चलाने के बजाय, आप इसे को के भीतर स्पष्ट रूप से कॉल कर रहे हैं!

स्विंगउटीसिटीज.inवोकलाटर() बाद में ईडीटी में आमंत्रण के लिए चलाने योग्य कतारबद्ध करता है! आप इसके बजाय SwingWorker का उपयोग करना चाहते हैं।

1

यहां मैंने अपनी कंपनी के ऐप के लिए क्या किया है, यह कानूनी कारणों से कुछ छद्म कोड है, लेकिन इसका जस्ट यह है कि यदि स्क्रीन अनुत्तरदायी है, तो यह जीयूआई को रीबूट करेगा। जब भी आप ईडीटी को बंद करने के लिए स्विंग यूटिलिटीज का उपयोग करते हैं, उसी उसी ब्लॉक में, दो वॉचर थ्रेड बनाएं। एक धागा स्विंग यूटिलिटीज का उपयोग कर ईडीटी थ्रेड पर बस एक क्रिया करेगा। एक और थ्रेड पहले धागे की निगरानी करेगा यह देखने के लिए कि क्या पहला धागा उत्तरदायी है। पहला धागा केवल प्रतिक्रिया को स्वीकार करेगा यदि यह एक बहुत ही सरल कमांड कर सकता है।

सेट isEDTCheck सच करने के लिए जब सामान्य फैशन में, झूठी डिबग मोड में

if (isEDTCheck) { 
     new Thread("EDTHeartbeat") { 
      @Override 
      public void run() { 
       Runnable thisThingYouDo = new Runnable() { 
        public void run() { 
         int x = 0; 
        } 
       }; 
       while (true) { 
        // first thread says we are waiting, aka bad state 
        edtwait=true; 
        try { 
         javax.swing.SwingUtilities.invokeAndWait(thisThingYouDo); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } catch (InvocationTargetException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
        // first thread says we are not waiting, good state 
        edtwait=false; 
        try { 
         Thread.sleep(5000); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
      } 
     }.start(); 

     new Thread("EDTValidator") { 
      @Override 
      public void run() { 
       while (true) { 
        // is first thread in bad state? 
        if (edtwait) { 
         try { 
          Thread.sleep(3000); 
          // after 3 seconds are we still in bad state? if so, get rid of initial frame, pop up a dialog box in AWT that does no commands 
          if (edtwait) { 
           mainFrame.setVisible(false); 
           new Dialog(); 
          } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
        } 
        try { 
         Thread.sleep(1000); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
      } 
     }.start(); 
    } 


    public class Dialog extends Frame { 
    private static final int WIDTH = 400; 
    private static final int HEIGHT = 300; 
    Frame f = null; 
    public Dialog() { 
     f = this; 
     hasSomethingBeenEntered=false; 
     this.setTitle("APP PROBLEM DETECTED"); 
     this.setSize(WIDTH, HEIGHT); 
     this.setLocation((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth() - myapp.width, 0); 
     Panel p1 = new Panel() { 
      @Override 
      public void paint(final Graphics g) { 
       int left = Dialog.WIDTH/2 - 45; // don't use WIDTH shadowed by Panel class 
       int top = Dialog.HEIGHT/2 - 20; // same as above 
       g.drawString("APP HAS DETECTED A PROBLEM", left, top); 
      } 
     }; 
     this.add("Center", p1); 

     this.setAlwaysOnTop(true); 
       TextArea tb = new TextArea("APP HAS DETECTED A MAJOR PROBLEM\nIT WILL NOW RESTART IN 5 SECONDS"); 
     this.add(tb); 
     this.setVisible(true); 
     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     restartApp(); 

    } 

    private void restartApp() { 
      Runtime.getRuntime().exec("cmd /c start cmd.exe /K \"cd C:\\Progra~1\\Common~1 && C:\\Progra~1\\Common~1\\MyAppDir\\myjavaapp.jar\""); 
      System.exit(0); 
     } 
संबंधित मुद्दे