2013-02-18 4 views
11

Ich versuche, einen Hintergrunddienst einzurichten, der Massenladen von Transaktionsdaten aus einer CSV-Datei ausführen würde. Dieser Hintergrunddienst wird von einer Menüelementaktion initiiert, die einer Methode in der Controller/Presenter-Klasse zugeordnet ist.JavaFX2: Kann ich einen Hintergrund Task/Service anhalten?

Immer wieder tauchen in der csv-Datei einige Daten auf, für die keine Stammdaten in der Datenbank gefunden werden können. Dies würde normalerweise dazu führen, dass der Upload erstickt und fehlschlägt.

In solchen Fällen möchte ich in der Lage sein, den Hintergrunddienst seine Verarbeitung unterbrechen zu lassen und einen Dialog von einer Präsentationsklasse aufzurufen, um Benutzereingaben aufzunehmen. Die Benutzereingabe würde verwendet werden, um eine Masterzeile in der Datenbank hinzuzufügen, nach der der Hintergrunddienst von dort fortgesetzt werden sollte, wo er unterbrochen wurde (nicht vom Anfang der CSV-Datei, sondern von der Zeile, die den Fehler verursacht hat).

Ist dies in JavaFX möglich, vielleicht mit der API javafx.concurrent? Wie würde ich das machen?

Antwort

20

Lösung

Wenn Ihr Hintergrundprozess eine Situation begegnet, wo er einen Benutzer zur Eingabe aufgefordert werden muss, verwenden Sie FutureTask in Platform.runLater-showAndWait Dialogaufforderung auf dem JavaFX Anwendungs-Thread ausgeführt. Im Hintergrundprozess verwenden Sie futureTask.get, um den Hintergrundprozess anzuhalten, bis der Benutzer die erforderlichen Werte eingegeben hat, die es dem Prozess ermöglichen, fortzufahren.


Beispielcode Snippet

Hier ist die Essenz der Code für diesen Ansatz, der in der Call-Methode Ihres Hintergrundprozess platziert werden können:

String nextText = readLineFromSource(); 
if ("MISSING".equals(nextText)) { 
    updateMessage("Prompting for missing text"); 
    FutureTask<String> futureTask = new FutureTask(
    new MissingTextPrompt() 
); 
    Platform.runLater(futureTask); 
    nextText = futureTask.get(); 
} 
... 
class MissingTextPrompt implements Callable<String> { 
    private TextField textField; 

    @Override public String call() throws Exception { 
    final Stage dialog = new Stage(); 
    dialog.setScene(createDialogScene()); 
    dialog.showAndWait(); 
    return textField.getText(); 
    } 
    ... 
} 

Probe Anwendung

Ich habe a small, complete sample application erstellt, um diesen Ansatz zu demonstrieren.

Die Ausgabe der Beispielanwendung ist:

promptingtaskdemooutput

Beispielausgabe Erklärung

Zeilen lesen, ohne Werte sind einfach nur braun fehlt. Zeilen mit einem Eingabeaufforderungswert haben einen hellgrünen Hintergrund. Vierzehn Zeilen wurden gelesen, die Hintergrundaufgabe hat bereits einmal an der 6. Zeile pausiert, der ein Wert fehlte. Der Benutzer wurde nach dem fehlenden Wert gefragt (zu dem der Benutzer xyzzy eingegeben hat), dann wurde der Prozess fortgesetzt, bis Zeile 14 ebenfalls fehlte und die Hintergrundaufgabe erneut unterbrochen wurde und ein weiterer Eingabeaufforderungsdialog angezeigt wurde.

+1

Ausgezeichnet, das sieht so aus, als würde es den Job erledigen. Vielen Dank. –

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, eine Lösung zu finden. Eine Änderung scheint mein Problem zu lösen. Allerdings sehe ich ein sehr merkwürdiges Verhalten in dem von Ihnen bereitgestellten Beispielcode. Wenn ich die Eingabezeichenfolge ändern und das erste Token auf "VERMISST" setzen, hängt das Programm; Das Dialogfenster zur Eingabe von Benutzereingaben wird nicht angezeigt. Aber, wenn ich fortfahre, es zu debuggen (in NetBeans 7.2), funktioniert es ganz gut. Irgendeine Idee, was hier passiert? –

+0

Es gab einen Fehler im Beispielcode. Das Beispiel verwendet 'container.getScene(). GetWindow()' innerhalb einer Aufgabe, die (korrekt) eine (nicht gemeldete) 'NullPointerException' ausgelöst hat, wenn der Container noch nicht zu einer Szene hinzugefügt wurde. Ich habe die Logikreihenfolge in dem Beispiel geändert, sodass die Aufgabe nicht gestartet wird, bis der Container, den es verwendet, der Szene hinzugefügt wurde (wodurch das Problem vermieden wird). [Aktualisierter Beispielcode verknüpft] (https://gist.github.com/jewelsea/4989970). – jewelsea