2017-11-26 38 views
2

私はvaadinフレームワーク内でいくつかのコードを呼び出そうとしていますが、これは長時間実行されているためプッシュで画面を更新しますが、それをキャンセルしてください。VaadinでSimpleTimeLimiter(Guava)を使用する方法

グアバのSimpleTimeLimiterクラスを使用しようとしていますが、何をしてもVaadinプロセスが停止しないように見えません。私はSimpleTimeLimiterUI.getCurrent().access()メソッドの内側と外側の両方に入れようと試みましたが、SimpleTimeLimiterTimeoutExceptionを投げたとしても、それらは両方ともプロセスを実行し続けます。私は、通常のスレッドと同じコードを使用している場合しかし、この方法は1秒以上かかる場合、それはTimeoutExceptionを投げると、通知ウィンドウをお付けいたします上記のコードでは...

public static void limitExecutionTime(Consumer<UI> lambda) 
{ 
    UI currentUI = UI.getCurrent(); 

    UI.getCurrent().access(() -> 
    { 
     try 
     { 
      SimpleTimeLimiter.create(Executors.newSingleThreadExecutor()).callWithTimeout(new Callable<Void>() 
      { 
       @Override 
       public Void call() 
       { 
        // This is needed to deal how Vaadin 8 handles UI's 
        UI.setCurrent(currentUI); 
        lambda.accept(); 
        return null; 
       } 
      }, 1, TimeUnit.SECONDS); 

     } catch (TimeoutException | InterruptedException | ExecutionException e) { 
      NotificationUtils.showError("Execution took beyond the maximum allowed time."); 
      currentUI.push(); 
     } 
    }); 
} 

を動作するようです。しかし、それはラムダを実行し続けます。私は反対のことを実行しようとしましたとpublic Void call()方法でUI.getCurrent().access()を置くが、これは正確に同じ結果を持っていた結果

...

あなたのバックグラウンドタスクの後に UI.accessを呼び出す必要があります

答えて

3

でそれを更新する準備ができていますいくつかのデータ。 accessメソッドを使用して、ユーザーが表示しているページの変更を行います。あなたの例では

バックグラウンドタスクの実行

、あなたはcallメソッドにタスクのキャンセルメッセージを渡す方法が欠落しています。外部イベントからのタスクキャンセル(たとえば、キャンセルボタンのクリック)を準備するには、タスク内でこれを考慮する必要があります。次の例は、Future.cancelを使用してキャンセルメソッドを提供する方法を示しています。

タスクを開始すると、これは次のような方法

private void simulateLongAndSlowCalculation() { 
    while (moreWorkTodo) { 
     if (Thread.currentThread().isInterrupted()) { 
      return; 
     } 
     try { 
      doSomeBlockingCallThatCanBeInterrupted(); 
     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); 
      return; 
     } 
    } 
} 

開始タスクとUI.accessで取り扱うことができ、実際のタスクインサイド

private void onCancelClick(Button.ClickEvent clickEvent) { 
    // This method is called from Vaadin UI thread. We will signal 
    // background task thread to stop. 
    futureResult.cancel(true); 
} 

、ビューは、タスクを作成し、それを提出しなければなりませんエグゼクティブサービス。

private void onButtonClick(Button.ClickEvent clickEvent) { 
    // This runTask creates important link to current UI and the background task. 
    // "this" object in these onTask methods is the UI object that we want 
    // to update. We need to have someway to pass UI object to background 
    // thread. UI.getCurrent() could be a parameter that is passed to the 
    // task as well. 
    Future<String> futureResult = taskService.runTask(
      this::onTaskDone, 
      this::onTaskCancel, 
      this::onTaskProgress); 
    progressDialog = new ProgressDialog(futureResult); 
    progressDialog.show(); 
} 

UIを更新する場合にのみ、UI.accessメソッドが必要です。この例では、それは次のような場合に発生する可能性が

  1. タスクは
  2. タスクの進捗状況が
  3. タスクは、以下の方法thisのすべてが参照する

注意をキャンセルしてしまっ更新されました正常に完了しましたタスクを開始したUIオブジェクト。そのため、他のユーザーのUIではなく、正しいUIを結果で更新しています。

コードでUI.setCurrentを呼び出す必要はありません。

https://github.com/m1kah/vaadin-background-task

編集:バックグラウンドタスクについて追加しましたセクション

private void onTaskProgress(double progress) { 
    logger.info("onTaskProgress: {}", progress); 
    access(() -> progressDialog.setProgress(progress)); 
} 

private void onTaskCancel() { 
    logger.info("onTaskCancel"); 
    access(() -> { 
     progressDialog.close(); 
     setResult("Cancelled"); 
    }); 
} 

private void onTaskDone(String result) { 
    logger.info("onTaskDone"); 
    access(() -> { 
     progressDialog.close(); 
     setResult(result); 
    }); 
} 

例プロジェクト

は、私がキャンセルボタンからのバックグラウンドタスクをキャンセルする方法を示してgithubのに別のプロジェクトをプッシュおよびUI.access。プロジェクトの別の例へのリンクを更新しました。

+0

私はそれを試みましたが、うまくいきませんでした。基本的に私は時間のx量後にUI.accessタスクを殺す方法を見つけることができません。つまり、表示されている方法ではなく、public Void呼び出しメソッドでUI.getCurrent()。access()を実行しました。同じ結果でしたが、TimeoutExceptionがあったとしてもaccess()は続きました。 –

+0

@StephaneGrenierトピック+についてより多くの回答を更新しました。より良いサンプルプロジェクトを作成しました:) – Mika

+0

詳細なサンプルとサンプルコードをありがとう、本当にありがとうございます。私が心配しているのは、コードとGuavaのSimpleTimeLimiterの違いは何ですか?車輪の再発明はたくさんありますか?私があなたのコードを正しく理解していれば、基本的にポーリングして割り込みの時間があるかどうかを確認していますか? –