私はメディア プレーヤーを設計しており、Movie クラスを設計しました。Movie クラスには、MediaInfo を継承する MovieInfo メンバーがあります。MediaInfo には、ファイル長、ファイル サイズ、ファイル パスなど、ムービー ファイルのメタデータを表すプロパティがいくつかあります。この情報を抽出するために、Shell32 を使用します。
問題は、Shell32 で提供されるメソッドが非常に遅いことです。データベースにムービーが 1 つある場合は問題ありませんが、ムービーが 10 個あると顕著になり始め、ムービーが 100 個あると、プログラムのロードに約 5 分かかります。実行時にムービーが表示され、プログラムの流れが再び停止します。
MediaInfo コンストラクターは Initialize メソッドを呼び出します。
/// <summary>
/// Initializes all the information variables of the class.
/// </summary>
private void Initialize()
{
Folder mediaFolder = Shell32Processing.GetShellFolder(this.path);
FolderItem media = Shell32Processing.GetShellFolderItem(this.path);
//initialize bit rate value
this.bitrate = mediaFolder.GetDetailsOf(media, 28);
//initialize date accessed value
this.dateAccessed = mediaFolder.GetDetailsOf(media, 5);
//initialize date created value
this.dateCreated = mediaFolder.GetDetailsOf(media, 4);
//initialize date modified value
this.dateModified = mediaFolder.GetDetailsOf(media, 3);
//initialize data rate value
this.dataRate = mediaFolder.GetDetailsOf(media, 279);
//initialize file name value
this.fileName = mediaFolder.GetDetailsOf(media, 155);
//initialize file type value
this.fileType = mediaFolder.GetDetailsOf(media, 181);
//initialize folder value
this.folder = mediaFolder.GetDetailsOf(media, 177);
//initialize folder name value
this.folderName = mediaFolder.GetDetailsOf(media, 175);
//initialize folder path value
this.folderPath = mediaFolder.GetDetailsOf(media, 176);
//initialize frame height value
this.frameHeight = mediaFolder.GetDetailsOf(media, 280);
//initialize frame rate value
this.frameRate = mediaFolder.GetDetailsOf(media, 281);
//initialize frame width value
this.frameWidth = mediaFolder.GetDetailsOf(media, 282);
//initialize length value
this.length = mediaFolder.GetDetailsOf(media, 27);
//initialize title value
this.title = FileProcessing.GetFileTitle(this.path);
//initialize total bitrate value
this.totalBitrate = mediaFolder.GetDetailsOf(media, 283);
//initialize size value
this.size = mediaFolder.GetDetailsOf(media, 1);
}
Shell32Processing.GetShellFolder メソッドは次のとおりです。
/// <summary>
/// Gets a Shell32 Folder, initialized to the directory of the file path.
/// </summary>
/// <param name="path">A string representing the file/folder path</param>
/// <returns>The Shell32 Folder.</returns>
public static Folder GetShellFolder(string path)
{
//extract the folder subpath from the file path
//i.e extract "C:\Example" from "C:\Example\example.avi"
string directoryPath = new FileInfo(path).Directory.ToString();
return new Shell().NameSpace(directoryPath);
}
そして、Shell32Processing.GetShellFolderItem メソッド:
/// <summary>
/// Gets a Shell32 FolderItem, initialized to the item specified in the file path.
/// </summary>
/// <param name="path">A string representing the file path.</param>
/// <returns>The Shell32 FolderItem.</returns>
/// <exception cref="System.ArgumentException">Thrown when the path parameter does not lead to a file.</exception>
public static FolderItem GetShellFolderItem(string path)
{
if (!FileProcessing.IsFile(path))
{
throw new ArgumentException("Path did not lead to a file", path);
}
int index = -1;
//get the index of the path item
FileInfo info = new FileInfo(path);
DirectoryInfo directoryInfo = info.Directory;
for (int i = 0; i < directoryInfo.GetFileSystemInfos().Count(); i++)
{
if (directoryInfo.GetFileSystemInfos().ElementAt(i).Name == info.Name) //we've found the item in the folder
{
index = i;
break;
}
}
return GetShellFolder(path).Items().Item(index);
}
GetDetailsOf (Shell32 で提供されるコード) への各呼び出しの処理には、信じられないほどの時間がかかります。最初は、プログラムの速度を大幅に低下させている原因を特定できなかったため、ANTS プロファイラーを使用してこれを見つけました。
問題は、Shell32 メソッドを最適化するにはどうすればよいか、できない場合は別の方法があるかということです。