C# 使用线程(任务)执行包含I/O的工作
我需要从一个文件中读取数据,处理并将结果写入另一个文件。我使用backgroundworker来显示进程状态。我写了类似这样的东西来在backgroundworker的DoWork事件中使用C# 使用线程(任务)执行包含I/O的工作,c#,multithreading,io,task,C#,Multithreading,Io,Task,我需要从一个文件中读取数据,处理并将结果写入另一个文件。我使用backgroundworker来显示进程状态。我写了类似这样的东西来在backgroundworker的DoWork事件中使用 private void ProcData(string fileToRead,string fileToWrite) { byte[] buffer = new byte[4 * 1024]; //fileToRead & file
private void ProcData(string fileToRead,string fileToWrite)
{
byte[] buffer = new byte[4 * 1024];
//fileToRead & fileToWrite have same size
FileInfo fileInfo = new FileInfo(fileToRead);
using (FileStream streamReader = new FileStream(fileToRead, FileMode.Open))
using (BinaryReader binaryReader = new BinaryReader(streamReader))
using (FileStream streamWriter = new FileStream(fileToWrite, FileMode.Open))
using (BinaryWriter binaryWriter = new BinaryWriter(streamWriter))
{
while (streamWriter.Position < fileInfo.Length)
{
if (streamWriter.Position + buffer.Length > fileInfo.Length)
{
buffer = new byte[fileInfo.Length - streamWriter.Position];
}
//read
buffer = binaryReader.ReadBytes(buffer.Length);
//proccess
Proc(buffer);
//write
binaryWriter.Write(buffer);
//report if procentage changed
//...
}//while
}//using
}
private void ProcData(字符串fileToRead,字符串fileToWrite)
{
字节[]缓冲区=新字节[4*1024];
//fileToRead和fileToWrite的大小相同
FileInfo FileInfo=newfileinfo(fileToRead);
使用(FileStream streamReader=newfilestream(fileToRead,FileMode.Open))
使用(BinaryReader BinaryReader=新的BinaryReader(streamReader))
使用(FileStream streamWriter=newfilestream(fileToWrite,FileMode.Open))
使用(BinaryWriter BinaryWriter=新的BinaryWriter(streamWriter))
{
while(streamWriter.PositionfileInfo.Length)
{
buffer=新字节[fileInfo.Length-streamWriter.Position];
}
//阅读
buffer=binaryReader.ReadBytes(buffer.Length);
//过程
Proc(缓冲区);
//写
写入(缓冲区);
//如果程序更改,请报告
//...
}//当
}//使用
}
但它比仅仅从fileToRead读取和写入fileToWrite要慢5倍,所以我考虑线程。我在网站上读到了一些问题,并尝试了类似的方法
private void ProcData2(字符串fileToRead,字符串fileToWrite)
{
int threadNumber=4;//例如
任务[]任务=新任务[threadNumber];
long[]startByte=新长[threadNumber];
long[]长度=新的long[threadNumber];
//将文件分割为螺纹编号(4)零件
//并更新startByte和length
var parentTask=Task.Run(()=>
{
对于(int i=0;i
{
Proc2(文件读取、文件写入、起始字节[i],长度[i]);
});
}
});
parentTask.Wait();
Task.WaitAll(任务);
}
//
私有void Proc2(字符串fileToRead、字符串fileToWrite、长fileStartByte、长partLength)
{
字节[]缓冲区=新字节[4*1024];
使用(FileStream streamReader=newfilestream(fileToRead,FileMode.Open,FileAccess.Read,FileShare.Read))
使用(BinaryReader BinaryReader=新的BinaryReader(streamReader))
使用(FileStream streamWriter=newfilestream(fileToWrite,FileMode.Open,FileAccess.Write,FileShare.Write))
使用(BinaryWriter BinaryWriter=新的BinaryWriter(streamWriter))
{
Seek(fileStartByte,SeekOrigin.Begin);
Seek(fileStartByte,SeekOrigin.Begin);
while(streamWriter.PositionfileStartByte+partLength)
{
buffer=新字节[fileStartByte+partLength-streamWriter.Position];
}
//阅读
buffer=binaryReader.ReadBytes(buffer.Length);
//过程
Proc(缓冲区);
//写
写入(缓冲区);
//如果程序更改,请报告
//...
}//当
}//使用
}
但我认为它有一些问题,每次切换任务时,它都需要再次寻找。我考虑读取文件,对Proc()使用线程,然后写入结果,但这似乎是错误的。如何正确执行?(从文件中读取缓冲区,使用任务处理并将其写入其他文件)
//===================================================================
根据皮特·柯克汉姆邮报,我修改了我的方法。我不知道为什么,但它对我不起作用。我添加了新的方法,以帮助他们。谢谢大家
private void ProcData3(string fileToRead, string fileToWrite)
{
int bufferSize = 4 * 1024;
int threadNumber = 4;//example
List<byte[]> bufferPool = new List<byte[]>();
Task[] tasks = new Task[threadNumber];
//fileToRead & fileToWrite have same size
FileInfo fileInfo = new FileInfo(fileToRead);
using (FileStream streamReader = new FileStream(fileToRead, FileMode.Open))
using (BinaryReader binaryReader = new BinaryReader(streamReader))
using (FileStream streamWriter = new FileStream(fileToWrite, FileMode.Open))
using (BinaryWriter binaryWriter = new BinaryWriter(streamWriter))
{
while (streamWriter.Position < fileInfo.Length)
{
//read
for (int g = 0; g < threadNumber; g++)
{
if (streamWriter.Position + bufferSize <= fileInfo.Length)
{
bufferPool.Add(binaryReader.ReadBytes(bufferSize));
}
else
{
bufferPool.Add(binaryReader.ReadBytes((int)(fileInfo.Length - streamWriter.Position)));
break;
}
}
//do
var parentTask = Task.Run(() =>
{
for (int th = 0; th < bufferPool.Count; th++)
{
int index = th;
//threads
tasks[index] = Task.Factory.StartNew(() =>
{
Proc(bufferPool[index]);
});
}//for th
});
//stop parent task(run childs)
parentTask.Wait();
//wait till all task be done
Task.WaitAll(tasks);
//write
for (int g = 0; g < bufferPool.Count; g++)
{
binaryWriter.Write(bufferPool[g]);
}
//report if procentage changed
//...
}//while
}//using
}
private void ProcData3(字符串fileToRead,字符串fileToWrite)
{
int bufferSize=4*1024;
int threadNumber=4;//示例
List bufferPool=新列表();
任务[]任务=新任务[threadNumber];
//fileToRead和fileToWrite的大小相同
FileInfo FileInfo=newfileinfo(fileToRead);
使用(FileStream streamReader=newfilestream(fileToRead,FileMode.Open))
使用(BinaryReader BinaryReader=新的BinaryReader(streamReader))
使用(FileStream streamWriter=newfilestream(fileToWrite,FileMode.Open))
使用(BinaryWriter BinaryWriter=新的BinaryWriter(streamWriter))
{
while(streamWriter.Position
{
Proc(缓冲池[索引]);
});
}//为了
});
//停止父任务(运行子任务)
parentTask.Wait();
//等到所有任务完成
private void ProcData3(string fileToRead, string fileToWrite)
{
int bufferSize = 4 * 1024;
int threadNumber = 4;//example
List<byte[]> bufferPool = new List<byte[]>();
Task[] tasks = new Task[threadNumber];
//fileToRead & fileToWrite have same size
FileInfo fileInfo = new FileInfo(fileToRead);
using (FileStream streamReader = new FileStream(fileToRead, FileMode.Open))
using (BinaryReader binaryReader = new BinaryReader(streamReader))
using (FileStream streamWriter = new FileStream(fileToWrite, FileMode.Open))
using (BinaryWriter binaryWriter = new BinaryWriter(streamWriter))
{
while (streamWriter.Position < fileInfo.Length)
{
//read
for (int g = 0; g < threadNumber; g++)
{
if (streamWriter.Position + bufferSize <= fileInfo.Length)
{
bufferPool.Add(binaryReader.ReadBytes(bufferSize));
}
else
{
bufferPool.Add(binaryReader.ReadBytes((int)(fileInfo.Length - streamWriter.Position)));
break;
}
}
//do
var parentTask = Task.Run(() =>
{
for (int th = 0; th < bufferPool.Count; th++)
{
int index = th;
//threads
tasks[index] = Task.Factory.StartNew(() =>
{
Proc(bufferPool[index]);
});
}//for th
});
//stop parent task(run childs)
parentTask.Wait();
//wait till all task be done
Task.WaitAll(tasks);
//write
for (int g = 0; g < bufferPool.Count; g++)
{
binaryWriter.Write(bufferPool[g]);
}
//report if procentage changed
//...
}//while
}//using
}