我希望方法splitFile
的单独异步线程应该运行,以便任务变得更快但代码不能正常工作。当我调试时,它到达行RecCnt = File.ReadAllLines(SourceFile).Length - 1;
并出来。请帮忙。
public delegate void SplitFile_Delegate(FileInfo file);
static void Main(string[] args)
{
DirectoryInfo d = new DirectoryInfo(@"D:\test\Perf testing Splitter"); //Assuming Test is your Folder
FileInfo[] Files = d.GetFiles("*.txt"); //Getting Text files
foreach (FileInfo file in Files)
{
SplitFile_Delegate LocalDelegate = new SplitFile_Delegate(SplitFile);
IAsyncResult R = LocalDelegate.BeginInvoke(file, null, null); //invoking the method
LocalDelegate.EndInvoke(R);
}
}
private static void SplitFile(FileInfo file)
{
try
{
String fname;
//int FileLength;
int RecCnt;
int fileCount;
fname = file.Name;
String SourceFile = @"D:\test\Perf testing Splitter\" + file.Name;
RecCnt = File.ReadAllLines(SourceFile).Length - 1;
fileCount = RecCnt / 10000;
FileStream fs = new FileStream(SourceFile, FileMode.Open);
using (StreamReader sr = new StreamReader(fs))
{
while (!sr.EndOfStream)
{
String dataLine = sr.ReadLine();
for (int x = 0; x < (fileCount + 1); x++)
{
String Filename = @"D:\test\Perf testing Splitter\Destination Files\" + fname + "_" + x + "by" + (fileCount + 1) + ".txt"; //test0by4
using (StreamWriter Writer = file.AppendText(Filename))
{
for (int y = 0; y < 10000; y++)
{
Writer.WriteLine(dataLine);
dataLine = sr.ReadLine();
}
Writer.Close();
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
答案 0 :(得分:3)
您的代码并不需要任何多线程。它甚至不需要异步处理 - 您最有可能使I / O饱和,除非您有多个驱动器作为数据源,否则您不会去通过添加并行性来改进它。
另一方面,您的代码正在读取每个文件两次。无缘无故,浪费内存,时间甚至CPU。相反,只需这样做:
FileStream fs = new FileStream(SourceFile, FileMode.Open);
using (StreamReader sr = new StreamReader(fs))
{
string line;
string fileName = null;
StreamWriter outputFile = null;
int lineCounter = 0;
int outputFileIndex = 0;
while ((line = sr.ReadLine()) != null)
{
if (fileName == null || lineCounter >= 10000)
{
lineCounter = 0;
outputFileIndex++;
fileName = @"D:\Output\" + fname + "_" + outputFileIndex + ".txt";
if (outputFile != null) outputFile.Dispose();
outputFile = File.AppendText(fileName);
}
outputFile.WriteLine(line);
lineCounter++;
}
}
如果你真的需要格式为XOutOfY
的文件名,那么你可以在之后重命名 - 它比阅读源文件要便宜很多,一行一行。或者,如果您不关心将整个文件同时保存在内存中,只需使用从ReadAllLines
获得的数组并对其进行迭代,而不是重新阅读。
为了使这更容易,您还可以使用foreach (var line in File.ReadLines(fileName))
。
如果你真的想让这个异步,那么处理它的方法是使用异步I / O,而不仅仅是假脱机新线程。因此,您可以await
使用StreamReader.ReadLineAsync
等
答案 1 :(得分:1)
您不需要调用EndInvoke,实际上所有EndInvoke都会等待您的返回值。由于SplitFile返回无效,我的猜测是有一个优化,因为你不需要等待任何东西,它只是忽略了等待。有关详细信息:C# Asynchronous call without EndInvoke?
话虽如此,您对Begin / EndInvoke的使用可能不会比串行编程更快(并且可能会稍微慢一点),因为您的for循环仍然是序列化的,并且您仍然在串行运行迭代。所有改变的是你使用代表看起来似乎没有必要。
你打算使用的是Parallel.ForEach(MSDN:https://msdn.microsoft.com/en-us/library/dd992001(v=vs.110).aspx),这可能会并行运行迭代。
编辑:正如其他人所提到的,让多个线程参与文件操作可能无法提高性能,因为您的文件操作可能是磁盘绑定的。从异步文件读/写中获得的主要好处可能是取消阻止UI更新的主线程。你需要指定你想要的东西&#34;表现&#34;如果你想要一个更好的答案。