Discussion:
IExtractImage in separate thread causes lock up
(too old to reply)
Skute
2005-09-20 08:55:41 UTC
Permalink
Hi,

Ive got a problem which is seriously plaguing me.
Im using the following code:

HBITMAP ExtractThumbnail(IShellFolder* pParentFolder, LPCITEMIDLIST
pidl)
{
CComPtr<IExtractImage> pExtract;
HBITMAP hBmpImage = NULL;
HRESULT hr = S_OK;

hr = pParentFolder->GetUIObjectOf(NULL, 1, &pidl, IID_IExtractImage,
NULL, reinterpret_cast<void **>(&pExtract));
if (pExtract != NULL) // Could be an early shell version where thumbs
werent supported
{
OLECHAR wszPathBuffer[MAX_PATH];
DWORD dwPriority = 0;
DWORD dwFlags = IEIFLAG_SCREEN;
SIZE szImage = {96, 96};
hr = pExtract->GetLocation(wszPathBuffer, MAX_PATH, &dwPriority,
&szImage, 32, &dwFlags);

// even if we've got shell v4.70+, not all files support thumbnails

if (hr == NOERROR)
hr = pExtract->Extract(&hBmpImage);

if (hBmpImage != NULL && hr != NOERROR)
{
::DeleteObject(hBmpImage);
hBmpImage = NULL;
}
}

return hBmpImage;
}



This code works beautifully in a single threaded application, but as
soon as i call this code in a separate thread, it locks up the GUI
(which is odd because its running in a separate thread!).

Has anyone got any clues as to why this may be happpening?
Im defiantely initialising COM etc.


The actual lock up occurs on the call to pExtract->Extract(&hBmpImage).
And usually occurs with the "My Shapes" directory in "My Documents". It
just pauses for about 3 seconds, then returns with hr = E_FAIL.

This is driving me nuts, please help.

Thanks,
matazz
2005-09-20 12:17:05 UTC
Permalink
I guess you have to initialize the Com Environnement, in appartment threaded
whith "CoInitializeEx"


#define _WIN32_DCOM
#include "objbase.h"


HRESULT hres = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
Post by Skute
Hi,
Ive got a problem which is seriously plaguing me.
HBITMAP ExtractThumbnail(IShellFolder* pParentFolder, LPCITEMIDLIST
pidl)
{
CComPtr<IExtractImage> pExtract;
HBITMAP hBmpImage = NULL;
HRESULT hr = S_OK;
hr = pParentFolder->GetUIObjectOf(NULL, 1, &pidl, IID_IExtractImage,
NULL, reinterpret_cast<void **>(&pExtract));
if (pExtract != NULL) // Could be an early shell version where thumbs
werent supported
{
OLECHAR wszPathBuffer[MAX_PATH];
DWORD dwPriority = 0;
DWORD dwFlags = IEIFLAG_SCREEN;
SIZE szImage = {96, 96};
hr = pExtract->GetLocation(wszPathBuffer, MAX_PATH, &dwPriority,
&szImage, 32, &dwFlags);
// even if we've got shell v4.70+, not all files support thumbnails
if (hr == NOERROR)
hr = pExtract->Extract(&hBmpImage);
if (hBmpImage != NULL && hr != NOERROR)
{
::DeleteObject(hBmpImage);
hBmpImage = NULL;
}
}
return hBmpImage;
}
This code works beautifully in a single threaded application, but as
soon as i call this code in a separate thread, it locks up the GUI
(which is odd because its running in a separate thread!).
Has anyone got any clues as to why this may be happpening?
Im defiantely initialising COM etc.
The actual lock up occurs on the call to pExtract->Extract(&hBmpImage).
And usually occurs with the "My Shapes" directory in "My Documents". It
just pauses for about 3 seconds, then returns with hr = E_FAIL.
This is driving me nuts, please help.
Thanks,
Skute
2005-09-20 15:54:20 UTC
Permalink
Thanks for the reply, but as i mentioned:
"Im defiantely initialising COM etc. "


I use:
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

Ive also tried using OleInitialize but that didnt work either.

I did try using the COINIT_MULTITHREADED flag in the application, but
it just resorts in my MFC dialog ASSERT'ing before its even loaded.
Jim Barry
2005-09-21 15:45:44 UTC
Permalink
Post by Skute
This code works beautifully in a single threaded application, but as
soon as i call this code in a separate thread, it locks up the GUI
You can't just pass a COM interface pointer to another thread and use it there. You're supposed to marshal the interface using CoMarshalInterThreadInterfaceInStream and CoGetInterfaceAndReleaseStream. Unfortunately, this usually doesn't work for shell interfaces, because most of them don't have marshalling support. In the case of IExtractImage, you can specify IEIFLAG_ASYNC to indicate that you would like to extract the image in a background thread. If GetLocation returns E_PENDING, you can make the call to Extract on another thread.
--
Jim Barry, MVP for Windows SDK
Skute
2005-09-22 08:33:25 UTC
Permalink
This post might be inappropriate. Click to display it.
nleontiev
2012-10-25 07:37:27 UTC
Permalink
Skute wrote on 09/22/2005 04:33 ET
Post by Skute
Im not actually passing an interface through to another thread, what
do is file a list control with a load of images, representing files
Then once the list control is full, i start the extraction thread. Thi
thread then loops through all the items currently in the list control
and then tries to extract a thumbnail icon for each. So all my shel
interface pointers are created, used and destroyed from within the ne
thread
If anyone has got any example code of how to use IEIFLAG_ASYNC and
background extraction thread that may well be useful (if it work
better than my current implementation)
Thanks
Did you find a solution for IExtractImage:Extract problem?

Loading...