Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.concurrent; 027 028import java.util.concurrent.Callable; 029import java.util.concurrent.FutureTask; 030import java.util.concurrent.atomic.AtomicReference; 031import javafx.application.Platform; 032import javafx.beans.property.*; 033import javafx.event.*; 034import static javafx.concurrent.WorkerStateEvent.*; 035 036/** 037 * <p> 038 * A fully observable implementation of a {@link FutureTask}. Tasks exposes 039 * additional state and observable properties useful for programming asynchronous 040 * tasks in JavaFX, as defined in the {@link Worker} interface. An implementation 041 * of Task must override the {@link javafx.concurrent.Task#call()} method. This method 042 * is invoked on the background thread. Any state which is used in this method 043 * must be safe to read and write from a background thread. For example, manipulating 044 * a live scene graph from this method is unsafe and will result in runtime 045 * exceptions. 046 * </p> 047 * <p> 048 * Tasks are flexible and extremely useful for the encapsulation of "work". Because 049 * {@link Service} is designed to execute a Task, any Tasks defined by the application 050 * or library code can easily be used with a Service. Likewise, since Task extends 051 * from FutureTask, it is very easy and natural to use a Task with the java concurrency 052 * {@link java.util.concurrent.Executor} API. Since a Task is Runnable, you 053 * can also call it directly (by invoking the {@link javafx.concurrent.Task#run()} method) 054 * from another background thread. This allows for composition of work, or pass it to 055 * a new Thread constructed and executed manually. Finally, since you can 056 * manually create a new Thread, passing it a Runnable, it is possible to use 057 * the following idiom: 058 * <pre><code> 059 * Thread th = new Thread(task); 060 * th.setDaemon(true); 061 * th.start(); 062 * </code></pre> 063 * Note that this code sets the daemon flag of the Thread to true. If you 064 * want a background thread to prevent the VM from existing after the last 065 * stage is closed, then you would want daemon to be false. However, if 066 * you want the background threads to simply terminate after all the 067 * stages are closed, then you must set daemon to true. 068 * </p> 069 * <p> 070 * Although {@link java.util.concurrent.ExecutorService} defines several methods which 071 * take a Runnable, you should generally limit yourself to using the <code>execute</code> 072 * method inherited from {@link java.util.concurrent.Executor}. 073 * </p> 074 * <p> 075 * As with FutureTask, a Task is a one-shot class and cannot be reused. See {@link Service} 076 * for a reusable {@link Worker}. 077 * </p> 078 * <p> 079 * Because the Task is designed for use with JavaFX GUI applications, it ensures 080 * that every change to its public properties, as well as change notifications 081 * for state, errors, and for event handlers, all occur on the main JavaFX application 082 * thread. Accessing these properties from a background thread (including the 083 * {@link #call()} method) will result in runtime exceptions being raised. 084 * </p> 085 * <p> 086 * It is <strong>strongly encouraged</strong> that all Tasks be initialized with 087 * immutable state upon which the Task will operate. This should be done by providing 088 * a Task constructor which takes the parameters necessary for execution of the Task. 089 * Immutable state makes it easy and safe to use from any thread and ensures 090 * correctness in the presence of multiple threads. 091 * </p> 092 * <p> 093 * In Java there is no reliable way to "kill" a thread in process. However, 094 * when <code>cancel</code> is called on a Task, it is important that 095 * the Task stop processing. A "run-away" Task might continue processing 096 * and updating the message, text, and progress properties even after the 097 * Task has been cancelled! In Java, cancelling a Task is a cooperative 098 * endeavor. The user of the Task will request that it be cancelled, and 099 * the author of the Task must check whether is has been cancelled within 100 * the body of the <code>call</code> method. There are two ways this can 101 * be done. First, the Task author may check the isCancelled method, 102 * inherited from <code>FutureTask</code>, to see whether the Task has 103 * been cancelled. Second, if the Task implementation makes use of any 104 * blocking calls (such as NIO InterruptibleChannels or Thread.sleep) and 105 * the task is cancelled while in such a blocking call, an 106 * InterruptedException is thrown. Task implementations which have blocking 107 * calls should recognize that an interrupted thread may be the signal for 108 * a cancelled task and should double check the isCancelled method to ensure 109 * that the InterruptedException was thrown due to the cancellation of the 110 * Task. 111 * </p> 112 * <h2>Examples</h2> 113 * <p> 114 * The following set of examples demonstrate some of the most common uses of 115 * Tasks. 116 * </p> 117 * 118 * <h3>A Simple Loop</h3> 119 * 120 * <p> 121 * The first example is a simple loop that does nothing particularly useful, 122 * but demonstrates the fundamental aspects of writing a Task correctly. This 123 * example will simply loop and print to standard out on each loop iteration. 124 * When it completes, it returns the number of times it iterated. 125 * </p> 126 * 127 * <pre><code> 128 * Task<Integer> task = new Task<Integer>() { 129 * @Override protected Integer call() throws Exception { 130 * int iterations; 131 * for (iterations = 0; iterations < 100000; iterations++) { 132 * if (isCancelled()) { 133 * break; 134 * } 135 * System.out.println("Iteration " + iterations); 136 * } 137 * return iterations; 138 * } 139 * }; 140 * </code></pre> 141 * 142 * <p> 143 * First, we define what type of value is returned from this Task. In this 144 * case, we want to return the number of times we iterated, so we will 145 * specify the Task to be of type Integer by using generics. Then, within 146 * the implementation of the <code>call</code> method, we iterate from 147 * 0 to 100000. On each iteration, we check to see whether this Task has 148 * been cancelled. If it has been, then we break out of the loop and return 149 * the number of times we iterated. Otherwise a message is printed to 150 * the console and the iteration count increased and we continue looping. 151 * </p> 152 * 153 * <p> 154 * Checking for isCancelled() in the loop body is critical, otherwise the 155 * developer may cancel the task, but the task will continue running 156 * and updating both the progress and returning the incorrect result 157 * from the end of the <code>call</code> method. A correct implementation 158 * of a Task will always check for cancellation. 159 * </p> 160 * 161 * <h3>A Simple Loop With Progress Notification</h3> 162 * 163 * <p> 164 * Similar to the previous example, except this time we will modify the 165 * progress of the Task in each iteration. Note that we have a choice 166 * to make in the case of cancellation. Do we want to set the progress back 167 * to -1 (indeterminate) when the Task is cancelled, or do we want to leave 168 * the progress where it was at? In this case, lets leave the progress alone 169 * and only update the message on cancellation, though updating the 170 * progress after cancellation is a perfectly valid choice. 171 * </p> 172 * 173 * <pre><code> 174 * Task<Integer> task = new Task<Integer>() { 175 * @Override protected Integer call() throws Exception { 176 * int iterations; 177 * for (iterations = 0; iterations < 10000000; iterations++) { 178 * if (isCancelled()) { 179 * updateMessage("Cancelled"); 180 * break; 181 * } 182 * updateMessage("Iteration " + iterations); 183 * updateProgress(iterations, 10000000); 184 * } 185 * return iterations; 186 * } 187 * }; 188 * </code></pre> 189 * 190 * <p> 191 * As before, within the for loop we check whether the Task has been 192 * cancelled. If it has been cancelled, we will update the Task's 193 * message to indicate that it has been cancelled, and then break as 194 * before. If the Task has not been cancelled, then we will update its 195 * message to indicate the current iteration and then update the 196 * progress to indicate the current progress. 197 * </p> 198 * 199 * <h3>A Simple Loop With Progress Notification And Blocking Calls</h3> 200 * 201 * <p> 202 * This example adds to the previous examples a blocking call. Because a 203 * blocking call may thrown an InterruptedException, and because an 204 * InterruptedException may occur as a result of the Task being cancelled, 205 * we need to be sure to handle the InterruptedException and check on the 206 * cancel state. 207 * </p> 208 * 209 * <pre><code> 210 * Task<Integer> task = new Task<Integer>() { 211 * @Override protected Integer call() throws Exception { 212 * int iterations; 213 * for (iterations = 0; iterations < 1000; iterations++) { 214 * if (isCancelled()) { 215 * updateMessage("Cancelled"); 216 * break; 217 * } 218 * updateMessage("Iteration " + iterations); 219 * updateProgress(iterations, 1000); 220 * 221 * // Now block the thread for a short time, but be sure 222 * // to check the interrupted exception for cancellation! 223 * try { 224 * Thread.sleep(100); 225 * } catch (InterruptedException interrupted) { 226 * if (isCancelled()) { 227 * updateMessage("Cancelled"); 228 * break; 229 * } 230 * } 231 * } 232 * return iterations; 233 * } 234 * }; 235 * </code></pre> 236 * 237 * <p> 238 * Here we have added to the body of the loop a <code>Thread.sleep</code> 239 * call. Since this is a blocking call, I have to handle the potential 240 * InterruptedException. Within the catch block, I will check whether 241 * the Task has been cancelled, and if so, update the message accordingly 242 * and break out of the loop. 243 * </p> 244 * 245 * <h3>A Task Which Takes Parameters</h3> 246 * 247 * <p> 248 * Most Tasks require some parameters in order to do useful work. For 249 * example, a DeleteRecordTask needs the object or primary key to delete 250 * from the database. A ReadFileTask needs the URI of the file to be read. 251 * Because Tasks operate on a background thread, care must be taken to 252 * make sure the body of the <code>call</code> method does not read or 253 * modify any shared state. There are two techniques most useful for 254 * doing this: using final variables, and passing variables to a Task 255 * during construction. 256 * </p> 257 * 258 * <p> 259 * When using a Task as an anonymous class, the most natural way to pass 260 * parameters to the Task is by using final variables. In this example, 261 * we pass to the Task the total number of times the Task should iterate. 262 * </p> 263 * 264 * <pre><code> 265 * final int totalIterations = 9000000; 266 * Task<Integer> task = new Task<Integer>() { 267 * @Override protected Integer call() throws Exception { 268 * int iterations; 269 * for (iterations = 0; iterations < totalIterations; iterations++) { 270 * if (isCancelled()) { 271 * updateMessage("Cancelled"); 272 * break; 273 * } 274 * updateMessage("Iteration " + iterations); 275 * updateProgress(iterations, totalIterations); 276 * } 277 * return iterations; 278 * } 279 * }; 280 * </code></pre> 281 * 282 * <p> 283 * Since <code>totalIterations</code> is final, the <code>call</code> 284 * method can safely read it and refer to it from a background thread. 285 * </p> 286 * 287 * <p> 288 * When writing Task libraries (as opposed to specific-use implementations), 289 * we need to use a different technique. In this case, I will create an 290 * IteratingTask which performs the same work as above. This time, since 291 * the IteratingTask is defined in its own file, it will need to have 292 * parameters passed to it in its constructor. These parameters are 293 * assigned to final variables. 294 * </p> 295 * 296 * <pre><code> 297 * public class IteratingTask extends Task<Integer> { 298 * private final int totalIterations; 299 * 300 * public IteratingTask(int totalIterations) { 301 * this.totalIterations = totalIterations; 302 * } 303 * 304 * @Override protected Integer call() throws Exception { 305 * int iterations = 0; 306 * for (iterations = 0; iterations < totalIterations; iterations++) { 307 * if (isCancelled()) { 308 * updateMessage("Cancelled"); 309 * break; 310 * } 311 * updateMessage("Iteration " + iterations); 312 * updateProgress(iterations, totalIterations); 313 * } 314 * return iterations; 315 * } 316 * } 317 * </code></pre> 318 * 319 * <p>And then when used:</p> 320 * 321 * <pre><code> 322 * IteratingTask task = new IteratingTask(8000000); 323 * </code></pre> 324 * 325 * <p>In this way, parameters are passed to the IteratingTask in a safe 326 * manner, and again, are final. Thus, the <code>call</code> method can 327 * safely read this state from a background thread.</p> 328 * 329 * <p>WARNING: Do not pass mutable state to a Task and then operate on it 330 * from a background thread. Doing so may introduce race conditions. In 331 * particular, suppose you had a SaveCustomerTask which took a Customer 332 * in its constructor. Although the SaveCustomerTask may have a final 333 * reference to the Customer, if the Customer object is mutable, then it 334 * is possible that both the SaveCustomerTask and some other application code 335 * will be reading or modifying the state of the Customer from different 336 * threads. Be very careful in such cases, that while a mutable object such 337 * as this Customer is being used from a background thread, that it is 338 * not being used also from another thread. In particular, if the background 339 * thread is reading data from the database and updating the Customer object, 340 * and the Customer object is bound to scene graph nodes (such as UI 341 * controls), then there could be a violation of threading rules! For such 342 * cases, modify the Customer object from the FX Application Thread rather 343 * than from the background thread.</p> 344 * 345 * <pre><code> 346 * public class UpdateCustomerTask extends Task<Customer> { 347 * private final Customer customer; 348 * 349 * public UpdateCustomerTask(Customer customer) { 350 * this.customer = customer; 351 * } 352 * 353 * @Override protected Customer call() throws Exception { 354 * // pseudo-code: 355 * // query the database 356 * // read the values 357 * 358 * // Now update the customer 359 * Platform.runLater(new Runnable() { 360 * @Override public void run() { 361 * customer.setF setFirstName(rs.getString("FirstName")); 362 * // etc 363 * } 364 * }); 365 * 366 * return customer; 367 * } 368 * } 369 * </code></pre> 370 * 371 * <h3>A Task Which Returns No Value</h3> 372 * 373 * <p> 374 * Many, if not most, Tasks should return a value upon completion. For 375 * CRUD Tasks, one would expect that a "Create" Task would return the newly 376 * created object or primary key, a "Read" Task would return the read 377 * object, an "Update" task would return the number of records updated, 378 * and a "Delete" task would return the number of records deleted. 379 * </p> 380 * 381 * <p> 382 * However sometimes there just isn't anything truly useful to return. 383 * For example, I might have a Task which writes to a file. Task has built 384 * into it a mechanism for indicating whether it has succeeded or failed 385 * along with the number of bytes written (the progress), and thus there is 386 * nothing really for me to return. In such a case, you can use the Void 387 * type. This is a special type in the Java language which can only be 388 * assigned the value of <code>null</code>. You would use it as follows: 389 * </p> 390 * 391 * <pre><code> 392 * final String filePath = "/foo.txt"; 393 * final String contents = "Some contents"; 394 * Task<Void> task = new Task<Void>() { 395 * @Override protected Void call() throws Exception { 396 * File file = new File(filePath); 397 * FileOutputStream out = new FileOutputStream(file); 398 * // ... and other code to write the contents ... 399 * 400 * // Return null at the end of a Task of type Void 401 * return null; 402 * } 403 * }; 404 * </code></pre> 405 * 406 * <h3>A Task Which Returns An ObservableList</h3> 407 * 408 * <p>Because the ListView, TableView, and other UI controls and scene graph 409 * nodes make use of ObservableList, it is common to want to create and return 410 * an ObservableList from a Task. When you do not care to display intermediate 411 * values, the easiest way to correctly write such a Task is simply to 412 * construct an ObservableList within the <code>call</code> method, and then 413 * return it at the conclusion of the Task.</p> 414 * 415 * <pre><code> 416 * Task<ObservableList<Rectangle>> task = new Task<ObservableList<Rectangle>>() { 417 * @Override protected ObservableList<Rectangle> call() throws Exception { 418 * updateMessage("Creating Rectangles"); 419 * ObservableList<Rectangle> results = FXCollections.observableArrayList(); 420 * for (int i=0; i<100; i++) { 421 * if (isCancelled()) break; 422 * Rectangle r = new Rectangle(10, 10); 423 * r.setX(10 * i); 424 * results.add(r); 425 * updateProgress(i, 100); 426 * } 427 * return results; 428 * } 429 * }; 430 * </code></pre> 431 * 432 * <p>In the above example, we are going to create 100 rectangles and return 433 * them from this task. An ObservableList is created within the 434 * <code>call</code> method, populated, and then returned.</p> 435 * 436 * <h3>A Task Which Returns Partial Results</h3> 437 * 438 * <p>Sometimes you want to create a Task which will return partial results. 439 * Perhaps you are building a complex scene graph and want to show the 440 * scene graph as it is being constructed. Or perhaps you are reading a large 441 * amount of data over the network and want to display the entries in a 442 * TableView as the data is arriving. In such cases, there is some shared state 443 * available both to the FX Application Thread and the background thread. 444 * Great care must be taken to <strong>never update shared state from any 445 * thread other than the FX Application Thread</strong>.</p> 446 * 447 * <p>The easiest way to do this is to take advantage of the {@link #updateValue(Object)} method. 448 * This method may be called repeatedly from the background thread. Updates are coalesced to 449 * prevent saturation of the FX event queue. This means you can call it as frequently as 450 * you like from the background thread but only the most recent set is ultimately set.</p> 451 * 452 * <pre><code> 453 * Task<Long> task = new Task<Long>() { 454 * @Override protected Long call() throws Exception { 455 * long a=0; 456 * long b=1; 457 * for (long i = 0; i < Long.MAX_VALUE; i++){ 458 * updateValue(a); 459 * a += b; 460 * b = a - b; 461 * } 462 * return a; 463 * } 464 * }; 465 * </code></pre> 466 * 467 * <p>Another way to do this is to expose a new property on the Task 468 * which will represent the partial result. Then make sure to use 469 * <code>Platform.runLater</code> when updating the partial result.</p> 470 * 471 * <pre><code> 472 * Task<Long> task = new Task<Long>() { 473 * @Override protected Long call() throws Exception { 474 * long a=0; 475 * long b=1; 476 * for (long i = 0; i < Long.MAX_VALUE; i++){ 477 * final long v = a; 478 * Platform.runLater(new Runnable() { 479 * @Override public void run() { 480 * updateValue(v); 481 * } 482 * } 483 * a += b; 484 * b = a - b; 485 * } 486 * return a; 487 * } 488 * }; 489 * </code></pre> 490 * 491 * <p>Suppose instead of updating a single value, you want to populate an ObservableList 492 * with results as they are obtained. One approach is to expose a new property on the Task 493 * which will represent the partial result. Then make sure to use 494 * <code>Platform.runLater</code> when adding new items to the partial 495 * result.</p> 496 * 497 * <pre><code> 498 * public class PartialResultsTask extends Task<ObservableList<Rectangle>> { 499 * // Uses Java 7 diamond operator 500 * private ReadOnlyObjectWrapper<ObservableList<Rectangle>> partialResults = 501 * new ReadOnlyObjectWrapper<>(this, "partialResults", 502 * FXCollections.observableArrayList(new ArrayList<Rectangle>())); 503 * 504 * public final ObservableList<Rectangle> getPartialResults() { return partialResults.get(); } 505 * public final ReadOnlyObjectProperty<ObservableList<Rectangle>> partialResultsProperty() { 506 * return partialResults.getReadOnlyProperty(); 507 * } 508 * 509 * @Override protected ObservableList<Rectangle> call() throws Exception { 510 * updateMessage("Creating Rectangles..."); 511 * for (int i=0; i<100; i++) { 512 * if (isCancelled()) break; 513 * final Rectangle r = new Rectangle(10, 10); 514 * r.setX(10 * i); 515 * Platform.runLater(new Runnable() { 516 * @Override public void run() { 517 * partialResults.get().add(r); 518 * } 519 * }); 520 * updateProgress(i, 100); 521 * } 522 * return partialResults.get(); 523 * } 524 * } 525 * </code></pre> 526 * 527 * <h3>A Task Which Modifies The Scene Graph</h3> 528 * 529 * <p>Generally, Tasks should not interact directly with the UI. Doing so 530 * creates a tight coupling between a specific Task implementation and a 531 * specific part of your UI. However, when you do want to create such a 532 * coupling, you must ensure that you use <code>Platform.runLater</code> 533 * so that any modifications of the scene graph occur on the 534 * FX Application Thread.</p> 535 * 536 * <pre><code> 537 * final Group group = new Group(); 538 * Task<Void> task = new Task<Void>() { 539 * @Override protected Void call() throws Exception { 540 * for (int i=0; i<100; i++) { 541 * if (isCancelled()) break; 542 * final Rectangle r = new Rectangle(10, 10); 543 * r.setX(10 * i); 544 * Platform.runLater(new Runnable() { 545 * @Override public void run() { 546 * group.getChildren().add(r); 547 * } 548 * }); 549 * } 550 * return null; 551 * } 552 * }; 553 * </code></pre> 554 * 555 * <h3>Reacting To State Changes Generically</h3> 556 * 557 * <p>Sometimes you may want to write a Task which updates its progress, 558 * message, text, or in some other way reacts whenever a state change 559 * happens on the Task. For example, you may want to change the status 560 * message on the Task on Failure, Success, Running, or Cancelled state changes. 561 * </p> 562 * <pre><code> 563 * Task<Integer> task = new Task<Integer>() { 564 * @Override protected Integer call() throws Exception { 565 * int iterations = 0; 566 * for (iterations = 0; iterations < 100000; iterations++) { 567 * if (isCancelled()) { 568 * break; 569 * } 570 * System.out.println("Iteration " + iterations); 571 * } 572 * return iterations; 573 * } 574 * 575 * @Override protected void succeeded() { 576 * super.succeeded(); 577 * updateMessage("Done!"); 578 * } 579 * 580 * @Override protected void cancelled() { 581 * super.cancelled(); 582 * updateMessage("Cancelled!"); 583 * } 584 * 585 * @Override protected void failed() { 586 * super.failed(); 587 * updateMessage("Failed!"); 588 * } 589 * }; 590 * </code></pre> 591 */ 592public abstract class Task<V> extends FutureTask<V> implements Worker<V>, EventTarget { 593 /** 594 * Used to send workDone updates in a thread-safe manner from the subclass 595 * to the FX application thread and workDone related properties. AtomicReference 596 * is used so as to coalesce updates such that we don't flood the event queue. 597 */ 598 private AtomicReference<ProgressUpdate> progressUpdate = new AtomicReference<>(); 599 600 /** 601 * Used to send message updates in a thread-safe manner from the subclass 602 * to the FX application thread. AtomicReference is used so as to coalesce 603 * updates such that we don't flood the event queue. 604 */ 605 private AtomicReference<String> messageUpdate = new AtomicReference<>(); 606 607 /** 608 * Used to send title updates in a thread-safe manner from the subclass 609 * to the FX application thread. AtomicReference is used so as to coalesce 610 * updates such that we don't flood the event queue. 611 */ 612 private AtomicReference<String> titleUpdate = new AtomicReference<>(); 613 614 /** 615 * Used to send value updates in a thread-safe manner from the subclass 616 * to the FX application thread. AtomicReference is used so as to coalesce 617 * updates such that we don't flood the event queue. 618 */ 619 private AtomicReference<V> valueUpdate = new AtomicReference<>(); 620 621 /** 622 * Creates a new Task. 623 */ 624 public Task() { 625 this(new TaskCallable<V>()); 626 } 627 628 /** 629 * This bit of construction trickery is necessary because otherwise there is 630 * no way for the main constructor to both create the callable and maintain 631 * a reference to it, which is necessary because an anonymous callable construction 632 * cannot reference the implicit "this". We leverage an internal Callable 633 * so that all the pre-built semantics around cancel and so forth are 634 * handled correctly. 635 * 636 * @param callableAdapter non-null implementation of the 637 * TaskCallable adapter 638 */ 639 private Task(final TaskCallable<V> callableAdapter) { 640 super(callableAdapter); 641 callableAdapter.task = this; 642 } 643 644 /** 645 * Invoked when the Task is executed, the call method must be overridden and 646 * implemented by subclasses. The call method actually performs the 647 * background thread logic. Only the updateProgress, updateMessage, and 648 * updateTitle methods of Task may be called from code within this method. 649 * Any other interaction with the Task from the background thread will result 650 * in runtime exceptions. 651 * 652 * @return The result of the background work, if any. 653 * @throws Exception an unhandled exception which occurred during the 654 * background operation 655 */ 656 protected abstract V call() throws Exception; 657 658 private ObjectProperty<State> state = new SimpleObjectProperty<State>(this, "state", State.READY); 659 final void setState(State value) { // package access for the Service 660 checkThread(); 661 final State s = getState(); 662 if (s != State.CANCELLED) { 663 this.state.set(value); 664 // Make sure the running flag is set 665 setRunning(value == State.SCHEDULED || value == State.RUNNING); 666 667 // Invoke the event handlers, and then call the protected methods. 668 switch (state.get()) { 669 case CANCELLED: 670 fireEvent(new WorkerStateEvent(this, WORKER_STATE_CANCELLED)); 671 cancelled(); 672 break; 673 case FAILED: 674 fireEvent(new WorkerStateEvent(this, WORKER_STATE_FAILED)); 675 failed(); 676 break; 677 case READY: 678 // This even can never meaningfully occur, because the 679 // Task begins life as ready and can never go back to it! 680 break; 681 case RUNNING: 682 fireEvent(new WorkerStateEvent(this, WORKER_STATE_RUNNING)); 683 running(); 684 break; 685 case SCHEDULED: 686 fireEvent(new WorkerStateEvent(this, WORKER_STATE_SCHEDULED)); 687 scheduled(); 688 break; 689 case SUCCEEDED: 690 fireEvent(new WorkerStateEvent(this, WORKER_STATE_SUCCEEDED)); 691 succeeded(); 692 break; 693 default: throw new AssertionError("Should be unreachable"); 694 } 695 } 696 } 697 @Override public final State getState() { checkThread(); return state.get(); } 698 @Override public final ReadOnlyObjectProperty<State> stateProperty() { checkThread(); return state; } 699 700 /** 701 * The onSchedule event handler is called whenever the Task state 702 * transitions to the SCHEDULED state. 703 * 704 * @return the onScheduled event handler property 705 */ 706 public final ObjectProperty<EventHandler<WorkerStateEvent>> onScheduledProperty() { 707 return getEventHelper().onScheduledProperty(); 708 } 709 710 /** 711 * The onSchedule event handler is called whenever the Task state 712 * transitions to the SCHEDULED state. 713 * 714 * @return the onScheduled event handler, if any 715 */ 716 public final EventHandler<WorkerStateEvent> getOnScheduled() { 717 return eventHelper == null ? null : eventHelper.getOnScheduled(); 718 } 719 720 /** 721 * The onSchedule event handler is called whenever the Task state 722 * transitions to the SCHEDULED state. 723 * 724 * @param value the event handler, can be null to clear it 725 */ 726 public final void setOnScheduled(EventHandler<WorkerStateEvent> value) { 727 getEventHelper().setOnScheduled(value); 728 } 729 730 /** 731 * A protected convenience method for subclasses, called whenever the 732 * state of the Task has transitioned to the SCHEDULED state. 733 * This method is invoked on the FX Application Thread after any listeners 734 * of the state property and after the Task has been fully transitioned to 735 * the new state. 736 */ 737 protected void scheduled() { } 738 739 /** 740 * The onRunning event handler is called whenever the Task state 741 * transitions to the RUNNING state. 742 * 743 * @return the onRunning event handler property 744 */ 745 public final ObjectProperty<EventHandler<WorkerStateEvent>> onRunningProperty() { 746 return getEventHelper().onRunningProperty(); 747 } 748 749 /** 750 * The onRunning event handler is called whenever the Task state 751 * transitions to the RUNNING state. 752 * 753 * @return the onRunning event handler, if any 754 */ 755 public final EventHandler<WorkerStateEvent> getOnRunning() { 756 return eventHelper == null ? null : eventHelper.getOnRunning(); 757 } 758 759 /** 760 * The onRunning event handler is called whenever the Task state 761 * transitions to the RUNNING state. 762 * 763 * @param value the event handler, can be null to clear it 764 */ 765 public final void setOnRunning(EventHandler<WorkerStateEvent> value) { 766 getEventHelper().setOnRunning(value); 767 } 768 769 /** 770 * A protected convenience method for subclasses, called whenever the 771 * state of the Task has transitioned to the RUNNING state. 772 * This method is invoked on the FX Application Thread after any listeners 773 * of the state property and after the Task has been fully transitioned to 774 * the new state. 775 */ 776 protected void running() { } 777 778 /** 779 * The onSucceeded event handler is called whenever the Task state 780 * transitions to the SUCCEEDED state. 781 * 782 * @return the onSucceeded event handler property 783 */ 784 public final ObjectProperty<EventHandler<WorkerStateEvent>> onSucceededProperty() { 785 return getEventHelper().onSucceededProperty(); 786 } 787 788 /** 789 * The onSucceeded event handler is called whenever the Task state 790 * transitions to the SUCCEEDED state. 791 * 792 * @return the onSucceeded event handler, if any 793 */ 794 public final EventHandler<WorkerStateEvent> getOnSucceeded() { 795 return eventHelper == null ? null : eventHelper.getOnSucceeded(); 796 } 797 798 /** 799 * The onSucceeded event handler is called whenever the Task state 800 * transitions to the SUCCEEDED state. 801 * 802 * @param value the event handler, can be null to clear it 803 */ 804 public final void setOnSucceeded(EventHandler<WorkerStateEvent> value) { 805 getEventHelper().setOnSucceeded(value); 806 } 807 808 /** 809 * A protected convenience method for subclasses, called whenever the 810 * state of the Task has transitioned to the SUCCEEDED state. 811 * This method is invoked on the FX Application Thread after any listeners 812 * of the state property and after the Task has been fully transitioned to 813 * the new state. 814 */ 815 protected void succeeded() { } 816 817 /** 818 * The onCancelled event handler is called whenever the Task state 819 * transitions to the CANCELLED state. 820 * 821 * @return the onCancelled event handler property 822 */ 823 public final ObjectProperty<EventHandler<WorkerStateEvent>> onCancelledProperty() { 824 return getEventHelper().onCancelledProperty(); 825 } 826 827 /** 828 * The onCancelled event handler is called whenever the Task state 829 * transitions to the CANCELLED state. 830 * 831 * @return the onCancelled event handler, if any 832 */ 833 public final EventHandler<WorkerStateEvent> getOnCancelled() { 834 return eventHelper == null ? null : eventHelper.getOnCancelled(); 835 } 836 837 /** 838 * The onCancelled event handler is called whenever the Task state 839 * transitions to the CANCELLED state. 840 * 841 * @param value the event handler, can be null to clear it 842 */ 843 public final void setOnCancelled(EventHandler<WorkerStateEvent> value) { 844 getEventHelper().setOnCancelled(value); 845 } 846 847 /** 848 * A protected convenience method for subclasses, called whenever the 849 * state of the Task has transitioned to the CANCELLED state. 850 * This method is invoked on the FX Application Thread after any listeners 851 * of the state property and after the Task has been fully transitioned to 852 * the new state. 853 */ 854 protected void cancelled() { } 855 856 /** 857 * The onFailed event handler is called whenever the Task state 858 * transitions to the FAILED state. 859 * 860 * @return the onFailed event handler property 861 */ 862 public final ObjectProperty<EventHandler<WorkerStateEvent>> onFailedProperty() { 863 return getEventHelper().onFailedProperty(); 864 } 865 866 /** 867 * The onFailed event handler is called whenever the Task state 868 * transitions to the FAILED state. 869 * 870 * @return the onFailed event handler, if any 871 */ 872 public final EventHandler<WorkerStateEvent> getOnFailed() { 873 return eventHelper == null ? null : eventHelper.getOnFailed(); 874 } 875 876 /** 877 * The onFailed event handler is called whenever the Task state 878 * transitions to the FAILED state. 879 * 880 * @param value the event handler, can be null to clear it 881 */ 882 public final void setOnFailed(EventHandler<WorkerStateEvent> value) { 883 getEventHelper().setOnFailed(value); 884 } 885 886 /** 887 * A protected convenience method for subclasses, called whenever the 888 * state of the Task has transitioned to the FAILED state. 889 * This method is invoked on the FX Application Thread after any listeners 890 * of the state property and after the Task has been fully transitioned to 891 * the new state. 892 */ 893 protected void failed() { } 894 895 private final ObjectProperty<V> value = new SimpleObjectProperty<V>(this, "value"); 896 private void setValue(V v) { checkThread(); value.set(v); } 897 @Override public final V getValue() { checkThread(); return value.get(); } 898 @Override public final ReadOnlyObjectProperty<V> valueProperty() { checkThread(); return value; } 899 900 private final ObjectProperty<Throwable> exception = new SimpleObjectProperty<Throwable>(this, "exception"); 901 private void _setException(Throwable value) { checkThread(); exception.set(value); } 902 @Override public final Throwable getException() { checkThread(); return exception.get(); } 903 @Override public final ReadOnlyObjectProperty<Throwable> exceptionProperty() { checkThread(); return exception; } 904 905 private final DoubleProperty workDone = new SimpleDoubleProperty(this, "workDone", -1); 906 private void setWorkDone(double value) { checkThread(); workDone.set(value); } 907 @Override public final double getWorkDone() { checkThread(); return workDone.get(); } 908 @Override public final ReadOnlyDoubleProperty workDoneProperty() { checkThread(); return workDone; } 909 910 private final DoubleProperty totalWork = new SimpleDoubleProperty(this, "totalWork", -1); 911 private void setTotalWork(double value) { checkThread(); totalWork.set(value); } 912 @Override public final double getTotalWork() { checkThread(); return totalWork.get(); } 913 @Override public final ReadOnlyDoubleProperty totalWorkProperty() { checkThread(); return totalWork; } 914 915 private final DoubleProperty progress = new SimpleDoubleProperty(this, "progress", -1); 916 private void setProgress(double value) { checkThread(); progress.set(value); } 917 @Override public final double getProgress() { checkThread(); return progress.get(); } 918 @Override public final ReadOnlyDoubleProperty progressProperty() { checkThread(); return progress; } 919 920 private final BooleanProperty running = new SimpleBooleanProperty(this, "running", false); 921 private void setRunning(boolean value) { checkThread(); running.set(value); } 922 @Override public final boolean isRunning() { checkThread(); return running.get(); } 923 @Override public final ReadOnlyBooleanProperty runningProperty() { checkThread(); return running; } 924 925 private final StringProperty message = new SimpleStringProperty(this, "message", ""); 926 @Override public final String getMessage() { return message.get(); } 927 @Override public final ReadOnlyStringProperty messageProperty() { return message; } 928 929 private final StringProperty title = new SimpleStringProperty(this, "title", ""); 930 @Override public final String getTitle() { return title.get(); } 931 @Override public final ReadOnlyStringProperty titleProperty() { return title; } 932 933 @Override public final boolean cancel() { 934 return cancel(true); 935 } 936 937 @Override public boolean cancel(boolean mayInterruptIfRunning) { 938 // Delegate to the super implementation to actually attempt to cancel this thing 939 boolean flag = super.cancel(mayInterruptIfRunning); 940 // If cancel succeeded (according to the semantics of the Future cancel method), 941 // then we need to make sure the State flag is set appropriately 942 if (flag) { 943 // If this method was called on the FX application thread, then we can 944 // just update the state directly and this will make sure that after 945 // the cancel method was called, the state will be set correctly 946 // (otherwise it would be indeterminate. However if the cancel method was 947 // called off the FX app thread, then we must use runLater, and the 948 // state flag will not be readable immediately after this call. However, 949 // that would be the case anyway since these properties are not thread-safe. 950 if (isFxApplicationThread()) { 951 setState(State.CANCELLED); 952 } else { 953 runLater(new Runnable() { 954 @Override public void run() { 955 setState(State.CANCELLED); 956 } 957 }); 958 } 959 } 960 // return the flag 961 return flag; 962 } 963 964 /** 965 * Updates the <code>workDone</code>, <code>totalWork</code>, 966 * and <code>progress</code> properties. Calls to updateProgress 967 * are coalesced and run later on the FX application thread, and calls 968 * to updateProgress, even from the FX Application thread, may not 969 * necessarily result in immediate updates to these properties, and 970 * intermediate workDone values may be coalesced to save on event 971 * notifications. <code>max</code> becomes the new value for 972 * <code>totalWork</code>. 973 * <p> 974 * <em>This method is safe to be called from any thread.</em> 975 * </p> 976 * 977 * @param workDone A value from Long.MIN_VALUE up to max. If the value is greater 978 * than max, then it will be clamped at max. 979 * If the value passed is negative then the resulting percent 980 * done will be -1 (thus, indeterminate). 981 * @param max A value from Long.MIN_VALUE to Long.MAX_VALUE. 982 * @see #updateProgress(double, double) 983 */ 984 protected void updateProgress(long workDone, long max) { 985 updateProgress((double)workDone, (double)max); 986 } 987 988 /** 989 * Updates the <code>workDone</code>, <code>totalWork</code>, 990 * and <code>progress</code> properties. Calls to updateProgress 991 * are coalesced and run later on the FX application thread, and calls 992 * to updateProgress, even from the FX Application thread, may not 993 * necessarily result in immediate updates to these properties, and 994 * intermediate workDone values may be coalesced to save on event 995 * notifications. <code>max</code> becomes the new value for 996 * <code>totalWork</code>. 997 * <p> 998 * <em>This method is safe to be called from any thread.</em> 999 * </p> 1000 * 1001 * @param workDone A value from Double.MIN_VALUE up to max. If the value is greater 1002 * than max, then it will be clamped at max. 1003 * If the value passed is negative, or Infinity, or NaN, 1004 * then the resulting percentDone will be -1 (thus, indeterminate). 1005 * @param max A value from Double.MIN_VALUE to Double.MAX_VALUE. Infinity and NaN are treated as -1. 1006 * @since 2.2 1007 */ 1008 protected void updateProgress(double workDone, double max) { 1009 // Adjust Infinity / NaN to be -1 for both workDone and max. 1010 if (Double.isInfinite(workDone) || Double.isNaN(workDone)) { 1011 workDone = -1; 1012 } 1013 1014 if (Double.isInfinite(max) || Double.isNaN(max)) { 1015 max = -1; 1016 } 1017 1018 if (workDone < 0) { 1019 workDone = -1; 1020 } 1021 1022 if (max < 0) { 1023 max = -1; 1024 } 1025 1026 // Clamp the workDone if necessary so as not to exceed max 1027 if (workDone > max) { 1028 workDone = max; 1029 } 1030 1031 if (isFxApplicationThread()) { 1032 _updateProgress(workDone, max); 1033 } else if (progressUpdate.getAndSet(new ProgressUpdate(workDone, max)) == null) { 1034 runLater(new Runnable() { 1035 @Override public void run() { 1036 final ProgressUpdate update = progressUpdate.getAndSet(null); 1037 _updateProgress(update.workDone, update.totalWork); 1038 } 1039 }); 1040 } 1041 } 1042 1043 private void _updateProgress(double workDone, double max) { 1044 setTotalWork(max); 1045 setWorkDone(workDone); 1046 if (workDone == -1) { 1047 setProgress(-1); 1048 } else { 1049 setProgress(workDone / max); 1050 } 1051 } 1052 1053 /** 1054 * Updates the <code>message</code> property. Calls to updateMessage 1055 * are coalesced and run later on the FX application thread, so calls 1056 * to updateMessage, even from the FX Application thread, may not 1057 * necessarily result in immediate updates to this property, and 1058 * intermediate message values may be coalesced to save on event 1059 * notifications. 1060 * <p> 1061 * <em>This method is safe to be called from any thread.</em> 1062 * </p> 1063 * 1064 * @param message the new message 1065 */ 1066 protected void updateMessage(String message) { 1067 if (isFxApplicationThread()) { 1068 this.message.set(message); 1069 } else { 1070 // As with the workDone, it might be that the background thread 1071 // will update this message quite frequently, and we need 1072 // to throttle the updates so as not to completely clobber 1073 // the event dispatching system. 1074 if (messageUpdate.getAndSet(message) == null) { 1075 runLater(new Runnable() { 1076 @Override public void run() { 1077 final String message = messageUpdate.getAndSet(null); 1078 Task.this.message.set(message); 1079 } 1080 }); 1081 } 1082 } 1083 } 1084 1085 /** 1086 * Updates the <code>title</code> property. Calls to updateTitle 1087 * are coalesced and run later on the FX application thread, so calls 1088 * to updateTitle, even from the FX Application thread, may not 1089 * necessarily result in immediate updates to this property, and 1090 * intermediate title values may be coalesced to save on event 1091 * notifications. 1092 * <p> 1093 * <em>This method is safe to be called from any thread.</em> 1094 * </p> 1095 * 1096 * @param title the new title 1097 */ 1098 protected void updateTitle(String title) { 1099 if (isFxApplicationThread()) { 1100 this.title.set(title); 1101 } else { 1102 // As with the workDone, it might be that the background thread 1103 // will update this title quite frequently, and we need 1104 // to throttle the updates so as not to completely clobber 1105 // the event dispatching system. 1106 if (titleUpdate.getAndSet(title) == null) { 1107 runLater(new Runnable() { 1108 @Override public void run() { 1109 final String title = titleUpdate.getAndSet(null); 1110 Task.this.title.set(title); 1111 } 1112 }); 1113 } 1114 } 1115 } 1116 1117 /** 1118 * Updates the <code>value</code> property. Calls to updateValue 1119 * are coalesced and run later on the FX application thread, so calls 1120 * to updateValue, even from the FX Application thread, may not 1121 * necessarily result in immediate updates to this property, and 1122 * intermediate values may be coalesced to save on event 1123 * notifications. 1124 * <p> 1125 * <em>This method is safe to be called from any thread.</em> 1126 * </p> 1127 * 1128 * @param value the new value 1129 * @since 8 1130 */ 1131 protected void updateValue(V value) { 1132 if (isFxApplicationThread()) { 1133 this.value.set(value); 1134 } else { 1135 // As with the workDone, it might be that the background thread 1136 // will update this value quite frequently, and we need 1137 // to throttle the updates so as not to completely clobber 1138 // the event dispatching system. 1139 if (valueUpdate.getAndSet(value) == null) { 1140 runLater(new Runnable() { 1141 @Override public void run() { 1142 Task.this.value.set(valueUpdate.getAndSet(null)); 1143 } 1144 }); 1145 } 1146 } 1147 } 1148 1149 /* 1150 * IMPLEMENTATION 1151 */ 1152 1153 private void checkThread() { 1154 if (!isFxApplicationThread()) { 1155 throw new IllegalStateException("Task must only be used from the FX Application Thread"); 1156 } 1157 } 1158 1159 // This method exists for the sake of testing, so I can subclass and override 1160 // this method in the test and not actually use Platform.runLater. 1161 void runLater(Runnable r) { 1162 Platform.runLater(r); 1163 } 1164 1165 // This method exists for the sake of testing, so I can subclass and override 1166 // this method in the test and not actually use Platform.isFxApplicationThread. 1167 boolean isFxApplicationThread() { 1168 return Platform.isFxApplicationThread(); 1169 } 1170 1171 /*************************************************************************** 1172 * * 1173 * Event Dispatch * 1174 * * 1175 **************************************************************************/ 1176 1177 private EventHelper eventHelper = null; 1178 private EventHelper getEventHelper() { 1179 if (eventHelper == null) { 1180 eventHelper = new EventHelper(this); 1181 } 1182 return eventHelper; 1183 } 1184 1185 /** 1186 * Registers an event handler to this task. Any event filters are first 1187 * processed, then the specified onFoo event handlers, and finally any 1188 * event handlers registered by this method. As with other events 1189 * in the scene graph, if an event is consumed, it will not continue 1190 * dispatching. 1191 * 1192 * @param <T> the specific event class of the handler 1193 * @param eventType the type of the events to receive by the handler 1194 * @param eventHandler the handler to register 1195 * @throws NullPointerException if the event type or handler is null 1196 */ 1197 public final <T extends Event> void addEventHandler( 1198 final EventType<T> eventType, 1199 final EventHandler<? super T> eventHandler) { 1200 getEventHelper().addEventHandler(eventType, eventHandler); 1201 } 1202 1203 /** 1204 * Unregisters a previously registered event handler from this task. One 1205 * handler might have been registered for different event types, so the 1206 * caller needs to specify the particular event type from which to 1207 * unregister the handler. 1208 * 1209 * @param <T> the specific event class of the handler 1210 * @param eventType the event type from which to unregister 1211 * @param eventHandler the handler to unregister 1212 * @throws NullPointerException if the event type or handler is null 1213 */ 1214 public final <T extends Event> void removeEventHandler( 1215 final EventType<T> eventType, 1216 final EventHandler<? super T> eventHandler) { 1217 getEventHelper().removeEventHandler(eventType, eventHandler); 1218 } 1219 1220 /** 1221 * Registers an event filter to this task. Registered event filters get 1222 * an event before any associated event handlers. 1223 * 1224 * @param <T> the specific event class of the filter 1225 * @param eventType the type of the events to receive by the filter 1226 * @param eventFilter the filter to register 1227 * @throws NullPointerException if the event type or filter is null 1228 */ 1229 public final <T extends Event> void addEventFilter( 1230 final EventType<T> eventType, 1231 final EventHandler<? super T> eventFilter) { 1232 getEventHelper().addEventFilter(eventType, eventFilter); 1233 } 1234 1235 /** 1236 * Unregisters a previously registered event filter from this task. One 1237 * filter might have been registered for different event types, so the 1238 * caller needs to specify the particular event type from which to 1239 * unregister the filter. 1240 * 1241 * @param <T> the specific event class of the filter 1242 * @param eventType the event type from which to unregister 1243 * @param eventFilter the filter to unregister 1244 * @throws NullPointerException if the event type or filter is null 1245 */ 1246 public final <T extends Event> void removeEventFilter( 1247 final EventType<T> eventType, 1248 final EventHandler<? super T> eventFilter) { 1249 getEventHelper().removeEventFilter(eventType, eventFilter); 1250 } 1251 1252 /** 1253 * Sets the handler to use for this event type. There can only be one such 1254 * handler specified at a time. This handler is guaranteed to be called 1255 * first. This is used for registering the user-defined onFoo event 1256 * handlers. 1257 * 1258 * @param <T> the specific event class of the handler 1259 * @param eventType the event type to associate with the given eventHandler 1260 * @param eventHandler the handler to register, or null to unregister 1261 * @throws NullPointerException if the event type is null 1262 */ 1263 protected final <T extends Event> void setEventHandler( 1264 final EventType<T> eventType, 1265 final EventHandler<? super T> eventHandler) { 1266 getEventHelper().setEventHandler(eventType, eventHandler); 1267 } 1268 1269 /** 1270 * Fires the specified event. Any event filter encountered will 1271 * be notified and can consume the event. If not consumed by the filters, 1272 * the event handlers on this task are notified. If these don't consume the 1273 * event either, then all event handlers are called and can consume the 1274 * event. 1275 * <p> 1276 * This method must be called on the FX user thread. 1277 * 1278 * @param event the event to fire 1279 */ 1280 public final void fireEvent(Event event) { 1281 checkThread(); 1282 getEventHelper().fireEvent(event); 1283 } 1284 1285 @Override 1286 public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) { 1287 return getEventHelper().buildEventDispatchChain(tail); 1288 } 1289 1290 /** 1291 * A struct like class that contains the last workDone update information. 1292 * What we do when updateProgress is called, is we create a new ProgressUpdate 1293 * object and store it. If it was null, then we fire off a new Runnable 1294 * using RunLater, which will eventually read the latest and set it to null 1295 * atomically. If it was not null, then we simply update it. 1296 */ 1297 private static final class ProgressUpdate { 1298 private final double workDone; 1299 private final double totalWork; 1300 1301 private ProgressUpdate(double p, double m) { 1302 this.workDone = p; 1303 this.totalWork = m; 1304 } 1305 } 1306 1307 /** 1308 * TaskCallable actually implements the Callable contract as defined for 1309 * the FutureTask class, and is necessary so as to allow us to intercept 1310 * the call() operation to update state on the Task as appropriate. 1311 * @param <V> 1312 */ 1313 private static final class TaskCallable<V> implements Callable<V> { 1314 /** 1315 * The Task that is going to use this TaskCallable 1316 */ 1317 private Task<V> task; 1318 1319 /** 1320 * Create a TaskCallable. The concurrent and other fields MUST be set 1321 * immediately after creation. 1322 */ 1323 private TaskCallable() { } 1324 1325 /** 1326 * Invoked by the system when it is time to run the client code. This 1327 * implementation is where we modify the state and other properties 1328 * and from which we invoke the events. 1329 * 1330 * @return The result of the Task call method 1331 * @throws Exception any exception which occurred 1332 */ 1333 @Override public V call() throws Exception { 1334 // If the Task is sent to an ExecutorService for execution, then we 1335 // will need to make sure that we transition first to the SCHEDULED 1336 // state before then transitioning to the RUNNING state. If the 1337 // Task was executed by a Service, then it will have already been 1338 // in the SCHEDULED state and setting it again here has no negative 1339 // effect. But we must ensure that SCHEDULED is visited before RUNNING 1340 // in all cases so that developer code can be consistent. 1341 task.runLater(new Runnable() { 1342 @Override public void run() { 1343 task.setState(State.SCHEDULED); 1344 task.setState(State.RUNNING); 1345 } 1346 }); 1347 // Go ahead and delegate to the wrapped callable 1348 try { 1349 final V result = task.call(); 1350 if (!task.isCancelled()) { 1351 // If it was not cancelled, then we take the return 1352 // value and set it as the result. 1353 task.runLater(new Runnable() { 1354 @Override public void run() { 1355 // The result must be set first, so that when the 1356 // SUCCEEDED flag is set, the value will be available 1357 // The alternative is not the case, because you 1358 // can assume if the result is set, it has 1359 // succeeded. 1360 task.updateValue(result); 1361 task.setState(State.SUCCEEDED); 1362 } 1363 }); 1364 return result; 1365 } else { 1366 // There may have been some intermediate result in the 1367 // task set from the background thread, so I want to be 1368 // sure to return the most recent intermediate value 1369 return task.getValue(); 1370 } 1371 } catch (final Throwable th) { 1372 // Be sure to set the state after setting the cause of failure 1373 // so that developers handling the state change events have a 1374 // throwable to inspect when they get the FAILED state. Note 1375 // that the other way around is not important -- when a developer 1376 // observes the causeOfFailure is set to a non-null value, even 1377 // though the state has not yet been updated, he can infer that 1378 // it will be FAILED because it can be nothing other than FAILED 1379 // in that circumstance. 1380 task.runLater(new Runnable() { 1381 @Override public void run() { 1382 task._setException(th); 1383 task.setState(State.FAILED); 1384 } 1385 }); 1386 // Some error occurred during the call (it might be 1387 // an exception (either runtime or checked), or it might 1388 // be an error. In any case, we capture the throwable, 1389 // record it as the causeOfFailure, and then rethrow. However 1390 // since the Callable interface requires that we throw an 1391 // Exception (not Throwable), we have to wrap the exception 1392 // if it is not already one. 1393 if (th instanceof Exception) { 1394 throw (Exception) th; 1395 } else { 1396 throw new Exception(th); 1397 } 1398 } 1399 } 1400 } 1401}