You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Task所有属性(含value)更新完成后接收Finished状态通知?

Alright, let's work through this JavaFX Task scenario. The core requirement is ensuring that whether our Task completes normally or gets cancelled, once it hits the finished state (and all properties are fully updated), our collected ObservableList<Rectangle> is set as the Task's value, and we have a reliable way to notify about this final state.

Here's a robust implementation that addresses all these needs:

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.scene.shape.Rectangle;
import javafx.application.Platform;

public class RectangleCollectionTask extends Task<ObservableList<Rectangle>> {

    @Override
    protected ObservableList<Rectangle> call() throws Exception {
        // Wrap our observable list to make it thread-safe for background operations
        ObservableList<Rectangle> collectedRects = FXCollections.synchronizedObservableList(
                FXCollections.observableArrayList()
        );

        // Replace this loop with your actual element collection logic
        for (int i = 0; i < 15; i++) {
            // Check for cancellation on each iteration to respond quickly
            if (isCancelled()) {
                break; // Exit early, return what we've collected so far
            }

            // Simulate a time-consuming collection step
            Thread.sleep(300);
            
            Rectangle newRect = new Rectangle(30, 30);
            collectedRects.add(newRect);

            // Optional: Update progress for UI feedback
            updateProgress(i + 1, 15);
        }

        // Return the collected list regardless of success/cancellation
        return collectedRects;
    }

    @Override
    protected void done() {
        super.done();
        // This method runs when the task enters the FINISHED state (success, failure, or cancellation)
        // All properties (including value) are fully updated by this point

        try {
            ObservableList<Rectangle> finalResults = getValue();
            
            // This is where you implement your notification logic
            // For UI updates, always wrap in Platform.runLater to stay on the JavaFX application thread
            Platform.runLater(() -> {
                System.out.println("Task completed! Collected " + finalResults.size() + " rectangles");
                // Example: Bind the list to a UI component, fire a custom event, etc.
                // myListView.setItems(finalResults);
                // someEventBus.fire(new TaskCompletedEvent(finalResults));
            });

        } catch (Exception e) {
            // Handle cases where the task failed (not cancelled)
            Platform.runLater(() -> {
                System.err.println("Task encountered an error: " + e.getMessage());
            });
        }
    }
}

Key Details to Note:

  • Thread-Safe List Handling: Since we're modifying the list from a background thread, we use FXCollections.synchronizedObservableList to prevent concurrent modification issues—JavaFX's default observable lists aren't thread-safe.
  • Responsive Cancellation: We check isCancelled() regularly during collection. If the task is cancelled, we stop processing immediately and return the elements we've already gathered, no data lost.
  • Reliable Final State Handling: Overriding done() is the best approach here. This method is guaranteed to run after the task enters the finished state, and all Task properties (like value) are fully updated at this point.
  • Safe UI Notifications: Any UI-related updates in the notification logic must be wrapped in Platform.runLater() to ensure they execute on the JavaFX application thread—this avoids runtime errors from cross-thread UI access.

How to Use This Task:

// Create the task instance
RectangleCollectionTask rectTask = new RectangleCollectionTask();

// Optional: Listen to state changes for additional feedback
rectTask.stateProperty().addListener((observable, oldState, newState) -> {
    if (newState == Task.State.CANCELLED) {
        System.out.println("Task was cancelled");
    }
});

// Start the task on a background thread (never run JavaFX Tasks on the main application thread!)
new Thread(rectTask).start();

// To cancel the task later (e.g., from a button click):
// rectTask.cancel();

内容的提问来源于stack exchange,提问作者kleopatra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:01:00