To add greg-449's comment:
Display.asyncExec()
queues the runnable to be run on the display's user-interface thread at the next reasonable opportunity. This does not cause the current thread to wait for the runnable to complete.
In the context of the Eclipse UI, user interface operations (like drawing, updating, and taking snapshots of the UI) must be performed in the UI thread. This is because the UI toolkit (SWT in this case) is not thread-safe, meaning it does not support concurrent modification from multiple threads.
When you call Display.asyncExec()
, the provided Runnable
will be executed asynchronously on the UI thread, allowing it to safely perform UI operations. This asynchronous execution also has the advantage of not blocking the current thread.
In your case, when you are setting the active page and taking a snapshot, these operations need to be performed on the UI thread.
By using Display.asyncExec()
, you are ensuring that these operations are performed on the UI thread, which can safely modify the UI. Additionally, since Display.asyncExec()
does not block, it allows the UI to update in between each invocation, which gives the UI a chance to display the page before the snapshot is taken.
In contrast, when you were just looping through and calling setActivePage()
and doSnapshot()
directly, all those operations were being queued up on the UI thread, but the UI did not have a chance to update and display the new active page before the next operation was performed. This is why you were only seeing the last page displayed and why the snapshots were not correct.
See also "Difference between syncExec() and asyncExec() of Display class".
Both asyncExec()
and syncExec()
are used to execute code on the UI thread, but there is a significant difference in their behavior:
syncExec(Runnable)
schedules the runnable to be run on the UI thread and then waits for it to finish before returning. This means that the calling thread is blocked until the runnable has completed its execution. This is useful when you need the result of the runnable's operation immediately, but it can cause a deadlock if used improperly.
asyncExec(Runnable)
also schedules the runnable to be run on the UI thread, but it returns immediately without waiting for the runnable to finish. This means that the calling thread can continue doing other work without waiting for the UI operations to complete.
In your case, you are looping over pages and taking a snapshot of each one. If you used syncExec()
, it would block on each iteration of the loop, waiting for the page to be displayed and the snapshot to be taken before moving on to the next iteration. This could potentially cause the UI to freeze, because the UI thread would be constantly busy and would not have time to process other events, like user input.
On the other hand, asyncExec()
schedules the operations to be performed and then immediately moves on to the next iteration. This allows the UI thread to interleave the execution of the scheduled operations with other tasks, such as processing user input and updating the display. This can result in a more responsive user interface, because it allows the UI to update in between the execution of your operations.
So asyncExec()
is more suitable for your use case, because it allows the UI to update in between the execution of your operations, which can lead to a more responsive and accurate user interface.