2011-09-08 5 views
6

मैं एक ऐसा एप्लिकेशन लिख रहा हूं जो SwingWorker का उपयोग करके अपने फ़ाइल मेनू क्रियाओं को निष्पादित करता है। प्रत्येक बुलाया गया विधि boolean मान देता है जो बताता है कि ऑपरेशन सफलतापूर्वक निष्पादित किया गया था या नहीं।मैं एक व्यस्त प्रतीक्षा के बिना स्विंगवर्कर के परिणाम * कैसे पढ़ूं?

फिलहाल मैं परिणाम के लिए इंतजार व्यस्त उपयोग कर रहा हूँ, इस तरह:

public boolean executeOperation() { 
    final SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() { 
     @Override 
     protected Boolean doInBackground() throws Exception { 
      // .. 

      if (aborted) { 
       return false; 
      } 

      // .. 

      return true; 
     } 
    }; 

    worker.execute(); 

    // busy wait 
    while (!worker.isDone()) 
     ; 

    try { 
     return worker.get().booleanValue(); 
    } catch (Exception e) { 
     // handle exceptions .. 
     return false; 
    } 
} 

वहाँ इस के हल के लिए एक कम मतदान तीव्र तरीका है?

worker.get() का उपयोग करते हुए सीधे काम नहीं होगा, यह ब्लॉक EDT के रूप में, समाप्त करने के लिए काम के लिए इंतजार - यहां तक ​​कि संवाद मैं SwingWorker के भीतर से खोलने के अर्थ चित्रित नहीं होगा।

संपादित करें: यदि संभव हो, तो मैं विधि (या कार्यकर्ता) को अपने परिणाम को असंकालिक रूप से संवाद करने के लिए टालना चाहूंगा। मैं कई छोटी विधियों को कार्यान्वित कर रहा हूं (फ़ाइल -> खुला, नया, बंद करें, सहेजें, सहेजें, बाहर निकलें) जो एक-दूसरे पर भरोसा करते हैं (यानी जब बाहर निकलने का प्रयास किया जाता है, बंद कॉल से बाहर निकलें, बंद हो सकता है कॉल करें, सेव करें कॉल सेव करें जैसा)। यह असीमित रूप से हल करने से कोड अधिक जटिल हो जाता है।

+0

आप हमेशा लूप में थ्रेड.sleep (100) डाल सकते हैं। –

+2

यह इस तथ्य को नहीं बदलेगा कि आप परिणाम के लिए मतदान कर रहे हैं, ऑब्जेक्ट करने की ऑब्जेक्ट करने के बजाए यह होने पर आपको बताएगा। – mcfinnigan

उत्तर

6

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

कार्य चलने के दौरान आप एक प्रगति पट्टी के साथ एक अवरुद्ध मोडल संवाद प्रदर्शित कर सकते हैं, और कार्य पूरा होने के बाद इसे छुपाएं।

विकल्प कुछ समय के लिए अवरुद्ध करना है, उम्मीद है कि कार्य खत्म हो जाएगा, और फिर बैकअप करने के असीमित तरीके से बैकअप लें। यह तर्क के रूप में get method taking a timeout का उपयोग करके किया जा सकता है।

+2

मुझे लगता है कि मेरी समस्या हल करती है: वर्तमान में मेरे सभी विधियां 'स्विंगवर्कर' का उपयोग करती हैं - जो एक समस्या प्रतीत होती है, क्योंकि मुझे परिणामों की प्रतीक्षा करनी है। मैं इन विधियों से 'स्विंगवर्कर' को हटा दूंगा और इसे केवल एक बार कॉल करूंगा, लेकिन 'स्विंगवर्कर' के अंदर सब कुछ निष्पादित कर दूंगा। – riwi

4

आप एक एसिंक्रोनस प्रतिमान का उपयोग कर सकते हैं। पर्यवेक्षक/पर्यवेक्षक को देखें और परिणाम को उस ऑब्जेक्ट में वापस स्थानांतरित करने के लिए नौकरी का उपयोग करें जो वर्तमान में मतदान कर रहा है।

+0

मैं इसे टालना चाहूंगा, क्योंकि यह मेरे कोड को अत्यधिक जटिल करेगा। मेरे पास कई शॉर्ट फ़ाइल मेनू ऑपरेशंस हैं (फ़ाइल -> ओपन, नया, क्लोज़, सेव, सेव, सेव, एग्जिट) जो एक-दूसरे पर भरोसा करते हैं (यानी जब बाहर निकलने का प्रयास किया जाता है, बंद कॉल से बाहर निकलें, बंद हो सकता है कॉल करें, सेव करें कॉल सेव करें जैसा)। – riwi

+1

काफी उचित है, यह जटिलता जोड़ता है और यदि आप श्रृंखला संचालन की योजना बना रहे हैं तो यह आदर्श नहीं हो सकता है। – mcfinnigan

4

worker.get() का उपयोग करते हुए सीधे काम नहीं होगा, यह ब्लॉक EDT के रूप में, समाप्त करने के लिए काम के लिए इंतजार - यहां तक ​​कि संवाद मैं SwingWorker के भीतर से खोलने के अर्थ चित्रित नहीं होगा।

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

पूर्ण एसिंक प्रोसेसिंग पर प्रतिक्रिया करने का सही तरीका में done() विधि को ओवरराइड कर रहा है।

अधिक जानकारी के लिए http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html भी देखें।

4

ऊपर दिए गए कई लोगों द्वारा उल्लिखित एक तरीका स्विंगवर्कर की पूरी विधि को ओवरराइड करना है। हालांकि अगर किसी कारण से आप स्विंगवर्कर के बाहर स्विंगवर्कर कोड पोस्ट करना चाहते हैं और कॉलिंग कोड में, आप स्विंगवर्कर के संपत्ति परिवर्तन समर्थन का लाभ उठा सकते हैं।बस एक स्विंगवर्कर लिस्टनर को स्विंगवर्कर में जोड़ें और राज्य संपत्ति की सुनें जिसमें "राज्य" का संपत्ति नाम है। इसके बाद आप स्विंगवर्कर के राज्य को get getate() विधि से निकाल सकते हैं। जब यह किया जाता है तो यह स्विंगवर्कर के स्टेट मूल्य को वापस कर देगा। स्टेटवैल्यू एनम। उदाहरण के लिए (एक जवाब से मैं इतने पर यहाँ another thread में दिया है):

if (turn == white) { 
    try { 
     final SwingWorker<Move, Void> mySwingWorker = new SwingWorker<Move, Void>() { 
      @Override 
      protected Move doInBackground() throws Exception { 
       Engine e = new Engine(); // Engine is implemented by runnable 
       e.start(); 
       Move m = e.getBestMove(board);     
       return m; 
      } 
     }; 

     mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() { 
      public void propertyChange(PropertyChangeEvent evt) { 
       if (StateValue.DONE == mySwingWorker.getState()) { 
       try { 
        Move m = mySwingWorker.get(); 

        // TODO: insert code to run on the EDT after move determined 

       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } catch (ExecutionException e) { 
        e.printStackTrace(); 
       } 
       } 
      } 
     }); 
     mySwingWorker.execute(); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 
0

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

public boolean executeOperation() { 
    final Semaphore semaphore = new Semaphore(1); 
    semaphore.acquire(1); // surround by try catch... 
    final SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() { 
     @Override 
     protected Boolean doInBackground() throws Exception { 
      // .. 

      if (aborted) { 
       semaphore.release(); 
       return false; 
      } 

      // .. 
      semaphore.release(); 
      return true; 
     } 
    }; 

    worker.execute(); 



    try { 
     semaphore.tryAcquire(1, 600, TimeUnit.SECONDS); // awakes when released or when 10 minutes are up. 
     return worker.get().booleanValue(); // blocks here if the task doesn't finish in 10 minutes. 
    } catch (Exception e) { 
     // handle exceptions .. 
     return false; 
    } 
} 

मुझे लगता है कि यह सभी स्थितियों के लिए आदर्श नहीं है। लेकिन मैंने सोचा कि यह एक वैकल्पिक दृष्टिकोण था जो मेरे लिए बहुत उपयोगी था।