我在共享上有大约1500个文件,我需要收集FileVersionInfo字符串。所以我在我的网关中创建了一个静态方法,如下所示:
private static string GetVersionInfo(string filepath)
{
FileVersionInfo verInfo = FileVersionInfo.GetVersionInfo(filepath);
return string.Format("{0}.{1}.{2}.{3}", verInfo.ProductMajorPart, verInfo.ProductMinorPart,
verInfo.ProductBuildPart, verInfo.ProductPrivatePart).Trim();
}
然后在与DegreeOfParallelism的PLINQ调用中使用FileAndVersion结构,因为这是与I / O相关的
resultList = dllFilesRows.AsParallel().WithDegreeOfParallelism(20)
.Select(r =>
{
var symbolPath = r.Filename;
return new FilenameAndVersion{Filename=symbolPath, Version=GetVersionInfo(symbolPath)};
})
.ToArray();
后来我将Struct,FileAndVersion修改为:
private struct FilenameAndVersion
{
private string _version, _filename;
public string Version { get { return _version; } }
public string Filename { get { return _filename; } }
private void SetVersion()
{
FileVersionInfo verInfo = FileVersionInfo.GetVersionInfo(this.Filename);
this._version = string.Format("{0}.{1}.{2}.{3}", verInfo.ProductMajorPart, verInfo.ProductMinorPart,
verInfo.ProductBuildPart, verInfo.ProductPrivatePart).Trim();
}
public FilenameAndVersion(string filename, string version)
{
this._filename = filename;
this._version = string.Empty;
SetVersion();
}
}
并使用它:
resultList = dllFilesRows.AsParallel().WithDegreeOfParallelism(20)
.Select(r =>
{
var symbolPath = r.Filename;
return new FilenameAndVersion(symbolPath, String.Empty);
})
.ToArray();
问题是,无论如何这是否会对我有所帮助并且是一种很好用的模式? 忘记提到文件位于连接有SAN的RAID 10的服务器上。
苏尼特
答案 0 :(得分:2)
如果您的所有文件都在同一个磁盘上,那么并行执行该操作根本不会有任何帮助。磁盘一次只能读取一个东西,所以你最好忘记它的并行性,抛弃线程开销并让它顺序运行。
如果你并行运行,那么你最终会得到的结果是一个只是在整个地方砰砰砰砰的磁盘,最终总体上读得更慢。
如果您的文件位于不同的物理驱动器上(或通过FTP等网络),请考虑对并行性进行更多控制,并将其划分为每个物理磁盘的单个任务。
我的建议是在你做出任何并行的坚定承诺之前对它进行基准测试。
答案 1 :(得分:1)
在处理文件I / O时使用TPL(或任何形式的并行)实际上更有可能减慢执行速度而不是加快速度,除非你有办法保证并行访问的文件是不同的物理磁盘或固态磁盘。顺序I / O中的磁存储往往比随机访问I / O好得多(你实际上是在这里强制执行)。
但是,与往常一样,您需要分析并实际衡量变更的影响。
澄清一下:在后台中运行昂贵的文件操作(最好使用I / O完成端口,FileVersionInfo
很遗憾不提供)是一件好事,为了避免阻止UI或ASP.NET请求,具体取决于您的环境。这与在 parallel 中运行它们有很大不同; TPL主要用于并行化 CPU密集型任务,其中多个CPU内核可以帮助您更快地完成操作。