The message property is created as a property that contains the "current message" for the task : i.e. the target use case is something like a status message. In this case, the use does not matter, the message that is stored in the property for only a very short time is never intercepted. Indeed, the documentation for updateMessage() states:
UpdateMessage calls are merged and started later on the FX application stream, so it calls updateMessage, even with FX The application stream may not necessarily lead to immediate updates, this property and intermediate message values ββcan be combined with save event notifications .
(my emphasis). In short, some of the values ββpassed to updateMessage(...) can never be set to messageProperty if they are quickly carried over by another value. In general, you can expect that only one value will be observed each time a frame is displayed on the screen (60 times per second or less). If you have a use case where it is important that you observe each value, you need to use a different mechanism.
A very naive implementation would simply use Platform.runLater(...) and directly update the text area. I do not recommend this implementation, since you run the risk of flood the FX application stream with too many calls (the exact reason updateMessage(...) combines calls), which makes the user interface unresponsive. However, this implementation will look like this:
for (int i = 1 ; i <= 300; i++) { String value = "\n" + i ; Platform.runLater(() -> ta_Statusbereich.appendText(value)); }
Another option is to make each operation a separate task and execute them all in parallel in some kind of artist. Add to the text area in each onSucceeded task. In this implementation, the order of the results is not specified, therefore, if the order is important, this is not a suitable mechanism:
final int numThreads = 8 ; Executor exec = Executors.newFixedThreadPool(numThreads, runnable -> { Thread t = Executors.defaultThreadFactory().newThread(runnable); t.setDaemon(true); return t ; }); // ... for (int i = 1; i <= 300; i++) { int value = i ; Task<String> task = new Task<String>() { @Override public String call() { // in real life, do real work here... return "\n" + value ; // value to be processed in onSucceeded } }; task.setOnSucceeded(e -> ta_Statusbereich.appendText(task.getValue())); exec.execute(task); }
If you want to do all this from one task and manage the order, you can put all messages in BlockingQueue , taking messages from the blocking queue and placing them in the text area of ββthe FX thread application. So that you do not fill the flow of FX applications with too many calls, you must consume messages from the queue no more than once to render the frame on the screen. You can use AnimationTimer for this purpose: the handle method is guaranteed to be called once to render the frame. It looks like this:
BlockingQueue<String> messageQueue = new LinkedBlockingQueue<>(); Task<Void> task = new Task<Void>() { @Override public Void call() throws Exception { final int numMessages = 300 ; Platform.runLater(() -> new MessageConsumer(messageQueue, ta_Statusbereich, numMessages).start()); for (int i = 1; i <= numMessages; i++) {