What is the best way to achieve this? (seperate Thread for listeningto events)

E

E. Naubauer

Hello everybody, I want to do the following:


I have an application that continuously receives and decodes images from
a stream. Since image decoding is an expensive task, I decided to
create a new thread that listens for incoming fragments and decodes them.

Basically my program has 2 classes:

class MainDialog extends Frame
{

Image currentImage;

public void receiveImages(...)
{
<this Method receives images from the decoding thread and
updates current image>
}
}


class ImageDecodingThread implements Runnable
{

public void run()
{
while(true)
{
//get next image from stream

//notify all Objects that are interested
in the current image and make them update their
local copies. Then they should redraw their window
content with the image
}
}
}


My question is what is the best way to do communication between the
ImageDecodingThread and the MainDialog object? I thought about
implementing the ChangeListener Interface in MainDialog and dispatching
ChangeEvent events from the ImageDecoding-Thread if a new image
arrives. However, using the standard EventListenerList model that
goes through the list of listening objects calling each objects
stateChanged Method is something I have only implemented between
objects used within the same thread. So does anyone know a good
standard approach to have one thread doing the whole gui and drawing
stuff and the other one receiving events and passing them to the
gui thread (especially typical synchronization issues)?

Thanks for any advice
 
E

E. Naubauer

you can alwayse pass objects to other objects even if they are in
seperate threads

My main concerns were

a) that the MainDialog needs to do the drawing of the images
the ImageListenerThread produces. Should I have the main
thread loop and wait for new images in ImageListenerThread and
cast repaint() everytime or have the ImageListenerThread control
the drawing as he receives a new image? it's because the main thread
has to modify an image after receiving it.

b) synchronizing access to the internal Variables of ImageListenerThread
that keep the image the main thread needs.
 
S

Stefan Schulz

E. Naubauer said:
My question is what is the best way to do communication between the
ImageDecodingThread and the MainDialog object? I thought about
implementing the ChangeListener Interface in MainDialog and dispatching
ChangeEvent events from the ImageDecoding-Thread if a new image
arrives. However, using the standard EventListenerList model that
goes through the list of listening objects calling each objects
stateChanged Method is something I have only implemented between
objects used within the same thread. So does anyone know a good
standard approach to have one thread doing the whole gui and drawing
stuff and the other one receiving events and passing them to the
gui thread (especially typical synchronization issues)?

You could use a queue. It would look somewhat like this:


class ImageHandler implements Runnable {
private Queue<Image> images = new LinkedList<Image>();

public void receivedImage(Image img){ // called from the decoder
synchronized (images){
images.offer(img);
images.notify();
}
}

public void run(){
while(true)
{
Image next;
//get next image from stream
synchronized(images){
next = images.poll();

while (next == null){
images.wait();
next = images.poll();
}
}


/*notify all Objects that are interested
*in the current image and make them update their
* local copies. Then they should redraw their window
*content with the image
*/
}
}
}
 
T

Thomas Weidenfeller

E. Naubauer said:
Hello everybody, I want to do the following:


I have an application that continuously receives and decodes images from
a stream. Since image decoding is an expensive task, I decided to
create a new thread that listens for incoming fragments and decodes them.

Firing some change event is IMHO a good idea. However, you have a
problems at hand, which you didn't mention:

Swing/AWT's single threading rule. Almost all GUI updates must be done
from the event dispatching thread, only.

So, when you fire your events from your separate thread, you are likely
calling GUI methods outside of the EDT. Firing an event is nothing
else than calling some method of an object. Typically one implements
event handler methods as if they are always only called by the EDT. So
one can assume your GUI event handlers are not prepared to be called by
some other thread, and will invoke Swing/AWT methods which should not be
called by someone else then the EDT.

You should therefore use invokeLater to schedule the events on the EDT.
However, if you schedule each notification of an event listener
separately via invokeLater, or if you let the whole notification loop
run on the EDT via one invokeLater is something I can't judge at the
moment. It really depends on how much listeners you have, and how much
time each one needs to update its GUI. I would probably schedule each
notification separately.
Basically my program has 2 classes:

class MainDialog extends Frame
{

Image currentImage;

public void receiveImages(...)
{
<this Method receives images from the decoding thread and
updates current image>

I assume this uses Swing or AWT methods. So this method must be called
from the EDT only.
My question is what is the best way to do communication between the
ImageDecodingThread and the MainDialog object?

Using event listeners seems a good idea to me. You just have to do them
right :) You seem a little bit confused about threads. You probably
want to read about the basics. Threads are not bound in any way to an
object as you seem to assume. The fact that they are not bound to an
object is actually the real problem at hand in your scenario. Your
processing thread will happily execute the event handlers which are
better not executed by anything else than the EDT.

/Thomas
 
E

E. Naubauer

Da ihr offensichtlich deutsch sprecht macht es wohl wenig Sinn
hier auf englisch zu reden. :)

Also, ich dachte jetzt an folgendes:

class IrgendeinFensterDasDieBilderZeichnet
extends Frame
implements Runnable
implements ChangeListener
{
Image currentImage;

public void run()
{
while(true)
{
< Eine Menge andere Sachen die mit dem aktuellen Bild gemacht werden
müssen >

synchronized(this)
{




repaint();
}

try {
Thread.sleep(10);
} catch(InterruptedException iex)
{
<...>
}
}
}

public void paint(Graphics g)
{
if(currentImage != null)
g.drawImage(currentImage,100,100,this);
}

//falls neues Bild vorhanden ruft der ImageDecodingThread
//bei allen Event-Empfängern diese Methode auf
public void stateChanged(ChangeEvent e)
{
synchronized(this)
{
//Bild des Frames wird neu gesetzt
ImageDecodingThread imt =
(ImageDecodingThread)e.getSource();

imt.getLatestImage();
}
}
}



Für Kommentare jeder Form bin ich dankbar
 
G

Gordon Beaton

Da ihr offensichtlich deutsch sprecht macht es wohl wenig Sinn hier
auf englisch zu reden. :)

Except that this is an english speaking newsgroup, and others might
like to follow the discussion.

/gordon
 
E

E. Naubauer

Gordon said:
Except that this is an english speaking newsgroup, and others might
like to follow the discussion.

/gordon

You're right. But since the important part is sourcecode it
won't hurt much.
 
S

Stefan Schulz

Thomas said:
What's wrong with a BlockingQueue. It'll simplify the other code.

I would have had to look up the javadocs, and knew this code by heart.
Otherwise, a BlockingQueue is fine if you need no fine-tuning or early
exit conditions.
 
T

Thomas Weidenfeller

Stefan said:
You could use a queue. It would look somewhat like this:


class ImageHandler implements Runnable {
private Queue<Image> images = new LinkedList<Image>();

Why implement own queuing, if there is already a queue involved? The
event queue. You have to notify the GUI about the changed image anyhow
via invokeLater or invokeAndWait (to avoid running in problems with the
EDT). Both place an event on the event queue, which is then processed in
series by the EDT.

Also, why implement an own list? You hold the listeners (the GUI windows
interested in changed, new images) in an EventListenerList in the model
(the image decode, producer) and you notify each of these listeners if
the image has changed (is ready, is new, etc.).


/Thomas
 
T

Thomas Hawtin

Thomas said:
Why implement own queuing, if there is already a queue involved? The
event queue. You have to notify the GUI about the changed image anyhow
via invokeLater or invokeAndWait (to avoid running in problems with the
EDT). Both place an event on the event queue, which is then processed in
series by the EDT.

The code presented is clearly not suitable for running in the EDT. Or at
least the Runnable section of the class is not. Using a different/inner
class for the Runnable probably would have been better. The code is,
however, suitable for the "ImageDecodingThread" (badly named class in
the original, as (correctly) it does not extend Thread).

It may well be worth implementing your own (non-blocking) queueing on
the EDT side of things. It can be very inefficient to pump large
quantities of events. Instead have an invocation event that pulls all
queued events off in one go. Only schedule the event when queueing onto
an empty queue. SwingWorker does something like this.

Tom Hawtin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top