none
开启线程实时加载文件的扩展信息,使用SheII32该组件加载文件的扩展信息到listview绑定的数据集合,但是运行测试时,抛出异常。如何解决这个问题? RRS feed

  • 问题

  • 项目需求中要求使用Listview展示文件或目录的信息,既要展示文件或目录的主要信息,也要展示文件的某些扩展信息,例如扩展名为.mp3文件的艺术家和专辑的信息也要展示。然后我运行测试发现,加载很多文件会造成程序假死,需要等待一段时间才能在listview上看到,

    于是我想到先加载文件名和路径到listview绑定的数据集合内,然后开启线程,对listview绑定的数据集合,进行迭代加载,并实时更新。这是我的思路。不过实体类得继承INotifyPropertyChanged

    然而在测试时抛出这个异常“ 无法将类型为“Shell32.ShellClass”的 COM 对象强制转换为接口类型“Shell32.IShellDispatch6”。此操作失败的原因是对 IID 为“{286E6F1B-7113-4355-9562-96B7E9D64C54}”的接口的 COM 组件调用 ”,无论是使用Task,还是使用Thread。都会抛出这个异常,

       private void loadFileExtendInfo(ObservableCollection<ItemModel> watch) { //为listview绑定的数据集合加载文件扩展信息的方法
                   Thread loadFileExtendThread = new Thread(() => {
                   foreach (var i in watch)
                    {
                        loadFileIo(i);
                    }
                });
                loadFileExtendThread.Start();
    
                //loadFileExtendTask = new Task(() =>
                //{
                //    loadFileExtendTask = null;
                //});
                //loadFileExtendTask.Start();
    
            }
    public  static void loadFileIo(ItemModel file)
            {
                ShellClass sh = new ShellClass();
                Folder dir = sh.NameSpace(System.IO.Path.GetDirectoryName(file.FileAddress));  //异常提示并指出这行代码
                FolderItem item = dir.ParseName(System.IO.Path.GetFileName(file.FileAddress));
                file.FilesCreateDate = dir.GetDetailsOf(item, 4);
                file.RecentlyVistedDateTime = dir.GetDetailsOf(item, 5);
                file.UpdateDateTime = dir.GetDetailsOf(item, 3);
                if (File.Exists(file.FileAddress))
                {
                    file.FileSizeFormat= dir.GetDetailsOf(item, 1);
                    file.FileType = Path.GetExtension(file.FileAddress);
                    switch (Path.GetExtension(file.FileAddress))
                    {
                        case ".png":
                           
                            file.ImgDimensions = dir.GetDetailsOf(item, 31);
                            break;
                        case ".jpg":
                            
                        
                            file.ImgDimensions = dir.GetDetailsOf(item, 31);
                            break;
                        case ".jpeg":
                           
                       
                            file.ImgDimensions = dir.GetDetailsOf(item, 31);
                            break;
                        case ".bmp":
                      
                            file.ImgDimensions = dir.GetDetailsOf(item, 31);
                            break;
                        case ".gif":
                        
                            file.ImgDimensions = dir.GetDetailsOf(item, 31);
                            break;
                        case ".mp3":
                            file.TitleName = dir.GetDetailsOf(item, 21);
                            file.Birate = dir.GetDetailsOf(item, 28);
                            file.Lenght = dir.GetDetailsOf(item, 27);
                            file.Author = dir.GetDetailsOf(item, 21);
                            file.RecordName = dir.GetDetailsOf(item, 14);
                            break;
                        case ".wav":
                            file.TitleName = dir.GetDetailsOf(item, 21);
                            file.Birate = dir.GetDetailsOf(item, 28);
                            file.Lenght = dir.GetDetailsOf(item, 27);
                            file.Author = dir.GetDetailsOf(item, 21);
                            file.RecordName = dir.GetDetailsOf(item, 14);
                            break;
                        default:
    
                            break;
                    }
                }
            }

    要如何做到读取大量文件的扩展信息时不造成程序假死?如果SheLll32不能在线程中使用的话,那有其他的能读取文件扩展信息的组件吗?我主要想读取音频文件的信息。

    2017年3月29日 9:15

答案

  • Hi 便携式家园,

    Shell32 这个Com组件是需要 STA(Single Thread Apartment) 线程的,支持STA的COM对象只能在创建它的线程里被使用,在其它线程如果再创建它就会失败,同一时刻只有一个线程可以访问对象.

    请使用:myThread.SetApartmentState(ApartmentState.STA); 或者在方法的入口位置使用[STAThread]来标记,指示执行这个方法的线程是单线程单元。

    请参考以下链接

    >>那有其他的能读取文件扩展信息的组件吗?我主要想读取音频文件的信息

    使用ID3 tag, ID3是最常用的MP3音频文件格式的元数据容器。

    Best Regards,

    Yohann Lu

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年3月30日 7:20
    版主