ما هي أفضل طريقة لإرجاع المتغيرات من syncExec؟

StackOverflow https://stackoverflow.com/questions/76300

  •  09-06-2019
  •  | 
  •  

سؤال

في تطبيق SWT Java الخاص بي، أرغب غالبًا في إرجاع المعلومات من داخل استدعاء Display.syncExec().أفضل طريقة وجدتها حتى الآن للقيام بذلك هي:

final ArrayList<Integer> result = new ArrayList<Integer>();
GUI.display().syncExec(new Runnable(){ public void run() {
   MessageBox mb = /* ... */;
    /* set up messagebox */
   result.add(mb.open());
}});
if (SWT.OK == result.get(0)) { /* ... */ }

أعتقد أن هذا مسموح به لأن ArrayList آمن لمؤشر الترابط، ولكن هل هناك حاوية أفضل يجب أن أستخدمها، أو طريقة أسهل تمامًا؟

هل كانت مفيدة؟

المحلول

ArrayList ليست آمنة للخيط.يمكنك الحصول على خيط آمن List مع Collections.synchronizedList.ومع ذلك، فمن الأسهل بكثير استخدام AtomicInteger في حالتك أو AtomicReference في حالة أكثر عمومية.

final AtomicInteger resultAtomicInteger = new AtomicInteger();
Display.getCurrent().syncExec(new Runnable() { 
    public void run() {
        MessageBox mb = /* ... */;
            /* set up messagebox */
        resultAtomicInteger.set(mb.open());
}});
if (SWT.OK == resultAtomicInteger.get()) { /* ... */ }

نصائح أخرى

لقد عالجت هذه المشكلة للتو وكانت محاولتي الأولى مماثلة - مجموعة أو قائمة من عناصر النوع المطلوب.لكن بعد فترة توصلت إلى شيء مثل هذا:

abstract class MyRunnable<T> implements Runnable{
    T result;
}
MyRunnable<Integer> runBlock = new MyRunnable<Integer>(){
   MessageBox mb = /* ... */;
    /* set up messagebox */
   result = mb.open();
}
GUI.display().syncExec(runBlock);
runBlock.result; //holds a result Integer

إنه أكثر ترتيبًا ويزيل المتغيرات الزائدة عن الحاجة.

بالمناسبة.كانت محاولتي الأولى حقًا هي استخدام UIThreadRunnable، لكنني لم أرغب في اعتماد SWTBot، لذلك أسقطت هذا الحل.بعد أن توصلت إلى الحل الخاص بي، اكتشفت أنهم يستخدمون عملاً مماثلاً هناك.

قائمة المصفوفات هي لا آمن للخيط.من الجهات ذات الصلة جافادوك:

لاحظ أن هذا التنفيذ غير متزامن.إذا وصلت مؤشرات الترابط المتعددة إلى مثيل ArrayList بشكل متزامن ، وعلى الأقل واحد من مؤشرات الترابط يعدل القائمة من الناحية الهيكلية ، فيجب مزامنة خارجيًا.

إذا كنت بحاجة إلى تنفيذ آمن للقائمة، فهناك (على الأقل) اثنين متوفران في JDK:CopyOnWriteArrayList وVector.

يمكنك استخدام مصفوفة Integer[1] لجعلها أكثر إيجازًا ولكن لا أعتقد أنه يمكنها تحديث متغير غير نهائي مباشرة من داخل فئة داخلية مجهولة.

final Integer[] result = new Integer[1];

اعتقدت أنه يتعين عليك إعلان النتائج نهائية (لكن هذا التغيير لن يؤثر على الكود الخاص بك).نظرًا لأن حظر الخيط الحالي حتى انتهاء الخيط الداخلي، لا أعتقد أنك بحاجة إلى القلق بشأن المزامنة (ولكن قد تحتاج إلى جعل المتغير ينتهك حتى ترى النتيجة).

إذا حدث هذا كثيرًا، فمن الأفضل استخدام نموذج الاشتراك/الإخطار بين العملية والعرض.تشترك طريقة العرض الخاصة بك في الحدث الذي يجب أن يؤدي إلى تشغيل مربع الرسالة هذا ويتم إعلامك عند استيفاء الشروط.

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