我有以下代码:
var lstMusicInfo = new List<MediaFile>();
var LocalMusic = Directory.EnumerateFiles(AppSettings.Default.ComputerMusicFolder, "*.*", SearchOption.AllDirectories).AsParallel().ToList<string>();
LocalMusic = (from a in LocalMusic.AsParallel()
where a.EndsWith(".mp3") || a.EndsWith(".wma")
select a).ToList<string>();
var DeviceMusic = adb.SyncMedia(this.dev, AppSettings.Default.ComputerMusicFolder, 1);
Parallel.ForEach(LocalMusic, new Action<string>(item =>
{
try
{
UltraID3 mFile = new UltraID3();
FileInfo fInfo;
mFile.Read(item);
fInfo = new FileInfo(item);
bool onDevice = true;
if (DeviceMusic.Contains(item))
{
onDevice = false;
}
// My Problem starts here
lstMusicInfo.Add(new MediaFile()
{
Title = mFile.Title,
Album = mFile.Album,
Year = mFile.Year.ToString(),
ComDirectory = fInfo.Directory.FullName,
FileFullName = fInfo.FullName,
Artist = mFile.Artist,
OnDevice = onDevice,
PTDevice = false
});
//Ends here.
}
catch (Exception) { }
}));
this.Dispatcher.BeginInvoke(new Action(() =>
{
lstViewMusicFiles.ItemsSource = lstMusicInfo;
blkMusicStatus.Text = "";
doneLoading = true;
}));
#endregion
}));
代码的第一部分给出了几乎即时的结果:
计算机上有5780个文件的地址。
获取Android设备上所有音乐文件的列表,将其与这些5780文件进行比较,并返回在计算机上找到但未在设备上找到的文件列表(在我的情况下,它会返回包含5118项的列表)。
下面的代码块是我的问题,我将数据填充到一个类中,然后将该类添加到List<T>
中,执行5780次需要60秒,我该如何改进它?
// My Problem starts here
lstMusicInfo.Add(new MediaFile
{
Title = mFile.Title,
Album = mFile.Album,
Year = mFile.Year.ToString(),
ComDirectory = fInfo.Directory.FullName,
FileFullName = fInfo.FullName,
Artist = mFile.Artist,
OnDevice = onDevice,
PTDevice = false
});
//Ends here.
更新 这是分析结果,我看到它显然为什么它减慢了&gt; _&gt; 我想我应该寻找一个不同的库来读取音乐文件信息。
答案 0 :(得分:2)
避免一次性加载所有内容的一种方法是在必要时延迟加载ID3信息。
您构建了MediaFile
实例,因此......
new MediaFile(filePath)
... MediaFile
看起来像下面这样。
internal sealed class MediaFile
{
private readonly Lazy<UltraID3> _lazyFile;
public MediaFile(string filePath)
{
_lazyFile = new Lazy<UltraID3>(() =>
{
var file = new UltraID3();
file.Read(filePath);
return file;
});
}
public string Title
{
get { return _lazyFile.Value.Title; }
}
// ...
}
这可能不如在后台尽可能快地加载它们那么理想,如果你执行类似MediaFiles.OrderBy(x => x.Title).ToList()
的操作并且没有任何延迟加载,那么你将不得不等待加载每个文件。 / p>
将它们加载到后台会使它们在后台加载完成后立即可用。但是,在后台加载完成之前,您可能不得不关注自己没有访问某些项目。
答案 1 :(得分:2)
您最大的瓶颈是new FileInfo(item)
,但您不需要FileInfo
来获取目录和文件名。您可以使用Path.GetDirectoryName
和Path.GetFileName
,因为不涉及I / O,所以必须加快速度。
UltraID3 mFile = new UltraID3();
//FileInfo fInfo;
mFile.Read(item);
//fInfo = new FileInfo(item);
bool onDevice = true;
if (DeviceMusic.Contains(item))
{
onDevice = false;
}
// My Problem starts here
lstMusicInfo.Add(new MediaFile()
{
Title = mFile.Title,
Album = mFile.Album,
Year = mFile.Year.ToString(),
ComDirectory = Path.GetDirectoryName(item), // fInfo.Directory.FullName,
FileFullName = Path.GetFileName(item), //fInfo.FullName,
Artist = mFile.Artist,
OnDevice = onDevice,
PTDevice = false
});
//Ends here.