Вызов SHGetFileInfo в потоке, чтобы избежать зависания пользовательского интерфейса.

В приложении.NET 4.0 (WPF)мы используем SHGetFileInfoдля получения значков оболочки для дерева каталогов. Поскольку в некоторых случаях это занимает довольно много времени (, т.е. для недостижимого сетевого диска или для гибкого диска)мы хотели сделать это в потоке, а затем обновить значок, когда он будет прочитан.

Вызов в основном такой же, теперь он просто выполняется внутри потока. Поскольку кто-то сказал, что поток должен быть STA, чтобы это работало, мы использовали Thread, а не ThreadPool для тестирования с теми же результатами. Использование ThreadPoolтакже не сработало.

SHGetFileInfoзавершается успешно (возвращает 1 ), но элемент hIcon в структуре равен нулю.

IntPtr GetIcon(string name)
{
    Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
    uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES | Shell32.SHGFI_SMALLICON;

    Shell32.SHGetFileInfo(
        name, System.IO.Directory.Exists(name) ? Shell32.FILE_ATTRIBUTE_DIRECTORY : Shell32.FILE_ATTRIBUTE_NORMAL,
        ref shfi, 
        (uint) System.Runtime.InteropServices.Marshal.SizeOf(shfi), 
        flags );
    return shfi.hIcon;
}

Тот же самый код отлично работает в потоке GUI. Что нужно сделать, чтобы функция работала из отдельного потока или, тем не менее, чтобы она работала без блокировки GUI-потока?


Обновление:Код вокруг этого в основном следующий:

var thread = new System.Threading.Thread(() => {
    var result = GetIcon("C:\\");
    //... do something with the result
});
thread.SetApartmentState(System.Threading.ApartmentState.STA);
thread.Start();

если оставить только строки внутри делегата потока, он работает нормально (но в потоке GUI, конечно).


Обновление:Сейчас мы просто вызываем вызов SHGetFileInfo, чтобы заставить его работать. Преимущество этого в том, что первоначальная проблема (страница с просмотром файлов не отображалась до тех пор, пока все иконки не были загружены)решена, хотя это означает, что страница зависает на каждой иконке. Но по крайней мере пользователь теперь видит, что что-то происходит. Мы все еще ищем реальное решение проблемы.

6
задан OregonGhost 13 April 2012 в 14:19
поделиться