我有这个。这是一个生成银行账户的申请
static void Main(string[] args)
{
string path = @"G:\BankNumbers";
var bans = BankAcoutNumbers.BANS;
const int MAX_FILES = 80;
const int BANS_PER_FILE = 81818182/80;
int bansCounter = 0;
var part = new List<int>();
var maxNumberOfFiles = 10;
Stopwatch timer = new Stopwatch();
var fileCounter = 0;
if (!Directory.Exists(path))
{
DirectoryInfo di = Directory.CreateDirectory(path);
}
try
{
while (fileCounter <= maxNumberOfFiles)
{
timer.Start();
foreach (var bank in BankAcoutNumbers.BANS)
{
part.Add(bank);
if (++bansCounter >= BANS_PER_FILE)
{
string fileName = string.Format("{0}-{1}", part[0], part[part.Count - 1]);
string outputToFile = "";// Otherwise you dont see the lines in the file. Just single line!!
Console.WriteLine("NR{0}", fileName);
string subString = System.IO.Path.Combine(path, "BankNumbers");//Needed to add, because otherwise the files will not stored in the correct folder!!
fileName = subString + fileName;
foreach (var partBan in part)
{
Console.WriteLine(partBan);
outputToFile += partBan + Environment.NewLine;//Writing the lines to the file
}
System.IO.File.WriteAllText(fileName, outputToFile);//Writes to file system.
part.Clear();
bansCounter = 0;
//System.IO.File.WriteAllText(fileName, part.ToString());
if (++fileCounter >= MAX_FILES)
break;
}
}
}
timer.Stop();
Console.WriteLine(timer.Elapsed.Seconds);
}
catch (Exception)
{
throw;
}
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
但是,这产生了8100万个银行账户记录,分成80个文件。但是我可以通过线程来加速这个过程吗?
答案 0 :(得分:1)
您正在谈论加快进程,其进程的瓶颈很可能是文件写入速度。您无法真正有效地将写入并行化到单个磁盘。
如果您生成一个只负责fileIO的工作线程,那么可能会看到速度略有提高。换句话说,创建一个缓冲区,让主线程将内容转储到其中,而另一个线程将其写入磁盘。它是经典的生产者/消费者动态。但是,我不会期待严重的速度提升。
另外请记住,写入控制台会降低你的速度,但你可以把它保留在主线程中,你可能会没事的。只需确保对缓冲区大小设置限制,并在缓冲区已满时让生产者线程挂起。
编辑:另外看一下L-Three提供的链接,使用 BufferedStream 会有所改进(并且可能无需渲染消费者线程)
答案 1 :(得分:0)
您的流程可分为两个步骤:
第一步可以并行完成,因为帐户之间没有依赖关系。这就是创建一个帐号xyz
,您不必依赖帐户xyz - 1
中的数据(因为它可能尚未创建)。
有问题的位是将数据写入文件。您不希望多个线程尝试访问和写入同一文件。添加锁定可能会使您的代码成为维护的噩梦。其他问题是它写入文件会减慢整个过程。
目前,在您的代码中创建帐户并在一个进程中写入文件。
您可以尝试分离这些过程。首先,您创建所有帐户并将其保留在某个集合中。这里可以安全地使用多线程。只有在创建了所有帐户后才能保存它们。
改善储蓄过程将需要更多的工作。您必须将所有帐户划分为8个单独的集合。对于每个集合,您将创建一个单独的文件然后,您可以获取第一个集合,第一个文件,并创建一个将数据写入文件的线程。第二个集合和第二个文件相同。等等。这8个进程可以并行运行,您不必担心多个线程会尝试访问同一个文件。
下面是一些伪代码来说明这个想法:
public void CreateAndSaveAccounts()
{
List<Account> accounts = this.CreateAccounts();
// Divide the accounts into separate batches
// Of course the process can (and shoudl) be automated.
List<List<Account>> accountsInSeparateBatches =
new List<List<Account>>
{
accounts.GetRange(0, 10000000), // Fist batch of 10 million
accounts.GetRange(10000000, 10000000), // Second batch of 10 million
accounts.GetRange(20000000, 10000000) // Third batch of 10 million
// ...
};
// Save accounts in parallel
Parallel.For(0, accountsInSeparateBatches.Count,
i =>
{
string filePath = string.Format(@"C:\file{0}", i);
this.SaveAccounts(accountsInSeparateBatches[i], filePath);
}
);
}
public List<Account> CreateAccounts()
{
// Create accounts here
// and return them as a collection.
// Use parallel processing wherever possible
}
public void SaveAccounts(List<Account> accounts, string filePath)
{
// Save accounts to file
// The method creates a thread to do the work.
}