Hi Kenneth,
yes, I agree that waiting for a short time to avoid race conditions is
problematic. If a computer is slow and Windows decides that it wants to
do something with the big mess named Registry, this can take quite a
while...
Fortunately, apart from what can be handled with
ImagePlus.waitTillActivated() there are only very few cases where I have
encountered a race condition (and it was not all my own poor programming).
Also note that you need the ImagePlus.waitTillActivated() only if you
care about the foreground window or events like WindowActivated.
I don't think that one can ever have an “all’s quiet” method. The user
may decide to do something with the mouse or keyboard at any time. This
may activate or close a window at any time.
In complex plugin sets, I found that "Close All" is one of the most
difficult to properly handle. When an image gets closed, the
ImageProcessors and their pixels array become null asynchronously. Thus,
a getProcessor() or getPixels() can return null at any time.
In a complex plugin, where closing an image can make some choices
invalid and therefore trigger further calculations on other image, there
is a good chance that one of these calculations leads to a
NullPointerException, because its image also gets closed asynchronously.
To avoid this kind of problems, one needs something like
ImageProcessor ip = imp.getProcessor();
if (ip == null) return; //seems the image was closed
Object pixels = ip.getPixels();
if (pixels == null) return; //seems the image was closed
Directly calling imp.getProcessor().someImageProcessorMethod can cause a
NullPointerException if the image imp was closed.
The closest to a “wait till all’s quiet” that I can think of is
EventQueue.invokeAndWait(Runnable) with an Runnable that does nothing.
If the EventQueue is currently busy, it will wait until the current
tasks of the EventQueue have finished. If some new tasks are entered
into the EventQueue while waiting, this won't wait for these events
being handled.
One could think about having this in a loop, until the EventQueue is
empty, but I have never tried. Roughly like this:
if (!EventQueue.isDispatchThread()) {
eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
do
EventQueue.invokeAndWait(new Runnable() {
final public void run() {} });
while (eventQueue.peekEvent() != null);
}
Nevertheless, it can't guarantee that there won't be a new event coming
a nanosecond later, still concurrent with your code execution.
Never do this in the EventQueue itself, unless you want to freeze
ImageJ. The "if" statement in the first line does that check.
Michael
________________________________________________________________
On 22.01.25 18:06, Kenneth R Sloan wrote:
Thanks for this explanation.
I work exclusively in Java and tend to prefer calling methods directly
rather than using “equivalent” IJ.run versions. When I do, I always
specify the image and never (well, hardly ever - and only when I forget)
depend on the “active window” when I can avoid it.
waitTillActivated() is new to me - I’ll start using it after every show().
I guess I haven’t been bitten by a race condition recently, although I have
dim memories of problems when dealing with keystrokes (my memory is too
hazy for specifics).
For my purposes, I suppose I really want an “all’s quiet” method that waits
until all operations are complete. Inserting waits always feels
problematic, since machine speeds can vary widely. Usually, I’m happy to
wait for much longer than may be necessary, but that always feels kludgy.
Grumble…
—-
Kenneth Sloan
(von meinem iPhone13 gesendet)
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html