سؤال

لقد جعلت من تقلبات الطلب ولكن هناك مشكلة واحدة في هذا وهي كما يلي:

لقد بدأت SwingWorker موضوع اسمه "الموضوع الرئيسي" من الحدث إرسال الموضوع و مرت JLabel مرجع واجهة المستخدم الرسومية إلى "الموضوع الرئيسي".

الآن بدأت 10 مواضيع من "الموضوع الرئيسي".

الآن أريد أن كل 10 مواضيع يجب تحديث JLabel.

كيف يمكن أن أفعل ذلك ؟

قال لي أحدهم أنني يمكن أن تفعل ذلك من خلال جعل كل 10 مواضيع فرعية من SwingWorker ثم استدعاء نشر("") طريقة تمرير السلسلة في أن "نشر" الأسلوب ومن ثم جمع كل ما نشر سلاسل من خلال الطريقة التالية في "الموضوع الرئيسي"

@Override
protected void process(List<String> labelStrings) {
    String count = labelStrings.get(labelStrings.size() - 1);
    label.setText(count); // label is a reference to a label in the GUI 
}
  1. هو النهج المذكور أعلاه هو الصحيح أن تفعل ذلك ؟
  2. أن 10 المواضيع تكون فرعية من SwingWorker?
  3. هل هناك أي طريقة أخرى للقيام بذلك ؟
هل كانت مفيدة؟

المحلول

  1. لا - هذا غير صحيح نهج إذا كنت تريد التحكم في عدد المواضيع نفسك.لماذا ؟ لأنه إذا نظرتم الى SwingWorker رمز سترى أنه يستخدم ThreadPoolExecutor داخليا تحتوي على الحد الأقصى من 10 مواضيع.إذا كنت انطلاق عدد من SwingWorker's بالتزامن سير باستخدام هذا المنفذ.ومع ذلك ، لديك أي سيطرة مباشرة إذا ما كانت الخلفية المواضيع يتم تنفيذها بالتوازي.
  2. انظر النقطة 1.
  3. بلدي الحل الموصى به ليكون:

    • إنشاء واحد SwingWorker.
    • داخل doInBackground() طريقة ركلة 10 المواضيع إما مباشرة أو باستخدام ExecutorService.
    • استخدام CountDownLatch أو CompletionService لمزامنة بين سيدك الموضوع (أي SwingWorker خلفية الموضوع) و المواضيع عامل.

على سبيل المثال

تحديد عدد المواضيع عامل أن تحتج وتعلن JLabel إلى تحديث.

final int nThreads = 10;
JLabel myLbl = new JLabel();

تحديد وحدة العمل نتمنى أن تنفيذ مثل Callable<String>.على String ستكون النتيجة استخدامها لتحديث JLabel.

private static class MyCallable implements Callable<String> {
  public String call() { ... }
}

الآن ركلة قبالة SwingWorker, والتي بدورها سوف تنطلق موازية متعددة العمال القيام بأي معالجة.العامل لن يعود النتيجة عبر الاتصال على done() (ومن هنا Void نوع) ولكن سوف مارشال المتوسطة String النتائج مرة أخرى على الأرجوحة الموضوع من خلال الاتصال process(String... chunks).

new SwingWorker<Void, String>() {
  // See method definitions below.
}.execute();

تعريف doInBackground() ينطلق العامل المواضيع كتلة لكل نتيجة استخدام CompletionService.

public Void doInBackground() throws Exception {
  // Define executor service containing exactly nThreads threads.
  ExecutorService execService = Executors.newFixedThreadPool(nThreads);


  // Define completion service that will contain the processing results.
  CompletionService compService = new ExecutorCompletionService(execService);    

  // Submit work to thread pool using the CompletionService.  Future<String>
  // instances will be added to the completion service's internal queue until complete.
  for (int i=0; i<nThreads; ++i) {
    compService.submit(new MyCallable());
  }

  // Take results from each worker as they appear and publish back to Swing thread.
  String result;
  while ((result = compService.take().get()) != null) {
    publish(result);
  }
}

الآن نقوم بتطبيق process(String... chunks) ببساطة تحديث JLabel عندما دعا.

public void process(String... chunks) {
  if (chunks.length > 0) {
    // Update label with last value in chunks in case multiple results arrive together.
    myLbl.setText(chunks[chunks.length - 1]);
  }
}

واخيرا تجاوز done() مارشال أي استثناءات على الأرجوحة الموضوع.

public void done() {
  try {
    get(); // Will return null (as per Void type) but will also propagate exceptions.
  } catch(Exception ex) {
    JOptionPane.show ... // Show error in dialog.
  }
}

نصائح أخرى

ربما أسهل النهج هو التفاف التعليمات البرمجية التي تحديثات واجهة المستخدم الرسومية في SwingUtilities.invokeLater(...) الأسلوب.

تحرير:في المواضيع الفردية كلما كنت ترغب في تحديث التسمية تفعل:

SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        label.setText(...);
    }
});

لماذا تحتاج 10 المواضيع ؟ لماذا لا أحد إضافية الخيط تفعل ؟

السؤال الحقيقي:ما هي المشكلة التي تحاول حلها ؟

للإجابة على الأسئلة المباشرة:

1) نعم, هذا هو النهج الصحيح 2) نعم, المواضيع يجب أن تكون SwingWorkers (إذا كنت تستخدم netbeans, يمكنك أيضا استخدام المهام التي فرعية من SwingWorker كذلك)

3) إذا كنت تريد أن يكون لها موضوع مستقل من edt;ثم كنت بحاجة إلى استخدام swingworker;لذلك هذا هو طريقة أن تفعل ذلك.

حظا سعيدا!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top