簡體   English   中英

如何在沒有*忙等待的情況下讀取SwingWorker的結果*?

[英]How do I read a SwingWorker's result *without* busy wait?

我正在編寫一個使用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打開的對話框也不會被繪制。

編輯:如果可能的話,我想避免方法(或工人)異步地傳達他們的結果。 我正在實現幾個相互依賴的簡短方法(文件 - >打開,新建,關閉,保存,另存為,退出)(即當試圖退出,退出呼叫關閉,關閉可能會調用保存,保存可能會調用保存如)。 異步解決這個問題似乎使代碼變得更加復雜。

SwingWorker的目的正是在后台啟動一些任務,而不是阻止EDT。 要么你想要同步的東西,要么你想要的東西阻止EDT,或者你想要異步的東西,后台任務應該使用SwingWorker的publish方法更新它的狀態。

您可以在任務運行時顯示帶有進度條的阻止模式對話框,並在任務完成后隱藏它。

另一種方法是阻塞一段時間,希望任務快速完成,然后備份到異步方式。 這可以使用get方法將超時作為參數來完成。

您可以使用異步范例。 查看Observer / Observable並使用該作業將結果傳回給當前正在進行輪詢的對象。

直接使用worker.get()是行不通的,因為它會阻止EDT,等待任務完成 - 這意味着即使我在SwingWorker打開的對話框也不會被繪制。

他們也沒有使用當前的代碼。 忙碌的等待會阻塞EDT,就像調用worker.get()一樣 - 只有一個事件調度線程,如果該線程在循環中旋轉或等待鎖定,則SwingWorker中的對話框也被阻止。 這里的問題是,如果一個方法在EDT上運行,它根本無法從異步操作(不占用EDT)返回一個值給它的調用者。

對完成的異步處理作出反應的正確方法是覆蓋SwingWorkerdone()方法。

另請參閱http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html以獲取更多信息。

上面幾個人提到的一種方法是覆蓋SwingWorker的done方法。 但是,如果出於某種原因,您希望在SwingWorker之外和調用代碼中發布SwingWorker代碼,則可以利用SwingWorker的屬性更改支持。 只需將一個PropertyChangeListener添加到SwingWorker並偵聽屬性名稱為“state”的state屬性。 然后,您可以使用其getState()方法提取SwingWorker的狀態。 完成后,它將返回SwingWorker.StateValue枚舉的DONE值。 例如(從我在SO的另一個帖子中給出的答案):

  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();
     }
  }

當我想要一個函數返回一個將在swing工作者中計算的值時,我遇到了類似的問題。 我不想簡單地讓那個線程阻止EDT。 我也不想阻止它。 所以我使用了這樣的信號量:

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;
    }
}

我想這對所有情況都不理想。 但我認為這是一種對我來說非常有用的替代方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM