Trouble with Threads blocking execution

L

Lunchtimemama

I have a UI with a gallery of thumbnail image previews. The
PictureBoxes are created and their Images are generated by a method
which quickly retrieves the icon for the filetype. Worker threads then
asynchronously retrieve and resize the full image previews and update
the PictureBox's Images when the new images are ready. The way I have
it set up now, the method which generates the filetype icons creates
and starts the new worker Threads. The problem is, the threads block
execution of the method. Here is the relevant code:
// This method is called to create a PictureBox's Image
private Image GetThumbnail(
string uri, // the filepath to the image
PictureBox pictureBox, // the PictureBox control - we need to know this so the worker thread can replace the right PictureBox's Image
int width, // the thumbnail width
int heigh // and the height
)
{
Image thumbnail = GetIcon(uri); // GetIcon returns an Image based on the filetype of the specified URI
ThumbnailThread thumbnailThread = new ThumbnailThread(uri, pictureBox, width, height, ThumbnailCallback); // See below for more on the ThumbnailThread class
Thread thread = new Thread(thumbnailThread.ThreadProc);
thread.Start();
return thumbnail; // we return the temporary thumbnail and the thread will update the PictureBox with the full image preview later
}

// This callback actually swaps the PictureBox's Image
private void ThumbnailCallback(Image image, PictureBox pictureBox)
{
pictureBox.Image = image;
}

and the ThumbnailThread class is thusly defined:
public class ThumbnailThread
{
private string _uri; // the filepath to the image
private PictureBox _pictureBox; // the PictureBox control
private int _width; // the width of the thumbnail
private int _height; // and the height
private ThumbnailThreadCallback _callback; // the callback method

public ThumbnailThread(string uri, PictureBox pictureBox, int width, int height, ThumbnailThreadCallback callback)
{
_uri = uri;
_pictureBox = pictureBox;
_width = width;
_height = height;
_callback = callback;
}

public void ThreadProc()
{
Image thumbnail = Image.FromFile(_uri); // get the whole image
thumbnail = MyClass.FixedSize(thumbnail, _width, _height); // FixedSize is a static method of MyClass that handles fixed proportion resizing
_callback(thumbnail, _pictureBox); // callback to the main thread
}
}

and the ThumbnailThreadCallback delegate looks like this:
public delegate void ThumbnailThreadCallback(Image image, PictureBox pictureBox);

I thought perhaps that scope of the Thread within GetThumbnail was
blocking execution, but I tried making a class-wide Thread[] array,
within which the worker threads were created, but execution was still
being blocked. Any clues?
 
R

rwbutts

I have a UI with a gallery of thumbnail image previews. The
PictureBoxes are created and their Images are generated by a method
which quickly retrieves the icon for the filetype. Worker threads then
asynchronously retrieve and resize the full image previews and update
the PictureBox's Images when the new images are ready. The way I have
it set up now, the method which generates the filetype icons creates
and starts the new worker Threads. The problem is, the threads block
execution of the method. Here is the relevant code:
[snip]

Your main problem I can see is that you are not marshalling the
"pictureBox.Image= image" final method call to the PictureBox control's
thread-- your worker thread is the thread trying to update the picturebox
when the image object creation is complete.

Change the "_callback(thumbnail, _pictureBox)" line with this:

_pictureBox.Invoke(_callback,new object[]{thumbnail,
_pictureBox)});

this will cause the callback invokation to be performed on the GUI thread
that owns the PictureBox's window handle. The Invoke() method will block
until the Gui thread has completed executing the given delegate.

See
http://weblogs.asp.net/justin_rogers/articles/126345.aspx
for instance for more about using threading with Gui objects.
 
L

Lunchtimemama

Neither of those solutions resolve the blocking problem. Note: I've
only tried them with local scope Threads. Is that an issue?
 
L

Lunchtimemama

I think the problem lies with Image.FromFile(). Does that function
syncronize with the main thread for some reason?
 

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

Top