Reading file associated icons from a secondary thread not returning correct icon - IconTest.zip (0/1

  • Thread starter Thread starter nagar
  • Start date Start date
N

nagar

I need to read the icons from a secondary thread so that the file list
is returned prompty in a listview.

I'm using a background worker object to retrieve icons asynchronously.
What happens is that the icons for certain files (I verified this
happens for xml and sln files on my system) are not correctly
retrieved (I get the standard blank icon).

I'm attaching a sample application that retrieves the icons
synchronously and asynchronously.
Thanks
Andrea
 
Hi Andrea,

I run your sample application and do see the problem on my side.

When I click the 'Read Async' button and navigate to a folder that contains
a .sln and a .xml files, the associated icons to the two files are the
standard blank icon.

However, when I click the 'Read Sync' button and navigate to the same
folder, the associated icons to the two files are correct.

I notice that when the application gets the associated icon asynchronous
using the SHGetFileInfo function, the returned iIcon memeber of the
structure specified by the psfi is of value 0, which is not correct.

public static Icon GetAssociatedIcon(string strPath, bool smallIcon)
{
....
int result = SHGetFileInfo(strPath, 0, out info, (uint)cbFileInfo,
flags);

if (info.hIcon != IntPtr.Zero)
{
retIcon = Icon.FromHandle(info.hIcon);
// when the SHGetFileInfo function is called by a thread
other than the UI thread, the info.iIcon memeber returns 0, which is not
correct
int index = info.iIcon;
}

return retIcon;
}

I will go on the research and get the result back to you ASAP.

I appreciate your patience!

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Thanks Linda. Hope there's a way to get the icons from a secondary
thread so that I can display the items in the list first and then load
the icons.
Thanks so much for your help.
Andrea
 
Hi Andrea,

Sorry for my delayed response. I was OOF yesterday.

I discussed this problem with my workmate. We found that the problem exists
only when the ApartmentState is set to MTA. If you comment out the
STAThreadAttribute on the static Main method, you should see that you can't
get the correct icons for .sln and .xml files even when you click the 'Read
Sync' button.

So the workaround to this problem is to set the ApartmentState of the
thread that the BackgroundWorker uses to STA. Unfortunately, I haven't
worked out how to do it until now.

Alternatively, you may create a Thread and set the thread's ApartmentState
to STA. The following is a sample.

private void AddIcons()
{
....
DisplayIcon();
}

delegate void ShowIconDelegate();
private void DisplayIcon()
{
if (this.InvokeRequired)
{
this.Invoke(new ShowIconDelegate(DisplayIcon));
}
else
{
int cont = 0;
for (; cont < this.iconlistAsync.Count; cont++)
{
this.imageListAsync.Images.Add(iconlistAsync[cont]);
listViewAsync.Items[cont].ImageIndex = cont;
DestroyIcon(iconlistAsync[cont].Handle);
}
}
}

private void btnReadAsync_Click(object sender, EventArgs e)
{
....
//backgroundWorker1.RunWorkerAsync();

Thread thd = new Thread(new ThreadStart(AddIcons));
thd.TrySetApartmentState(ApartmentState.STA);
thd.Start();
}

Hope this helps.


Sincerely,
Linda Liu
Microsoft Online Community Support
 
Thanks so much Linda. You are really an asset for this newsgroup. I
tried your solution and it worked like a charm.

I wonder if I could use a thread pool to simultaneously load more
icons to speed things up a little bit more. However, it's already a
big improvement.

Thanks.
Andrea
 
Hi Andrea,

Thank you for your feedback.

Thread pooling is not compatible with the single-threaded apartment (STA)
model. However, in your scenario, the thread must to be set to the STA
mode. So it's impossible to use thread pooling in your application.

Hope this helps.
If you have any other concerns, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support
 
Hi Andrea,

How about the problem now?

If you have any question, please feel free to let me know.

Thank you for using our MSDN Managed Newsgroup Support Service!

Sincerely,
Linda Liu
Microsoft Online Community Support
 
Back
Top