C# 带写入文件系统的线程

C# 带写入文件系统的线程,c#,C#,我有这个。它是一个用于生成银行帐户的应用程序 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

我有这个。它是一个用于生成银行帐户的应用程序

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();
    }
static void Main(字符串[]args)
{
字符串路径=@“G:\BankNumbers”;
var bans=BankAcoutNumbers.bans;
const int MAX_FILES=80;
const int BANS_PER_FILE=818182/80;
国际银行中心=0;
var part=新列表();
var maxNumberOfFiles=10;
秒表计时器=新秒表();
var fileCounter=0;
如果(!Directory.Exists(path))
{
DirectoryInfo di=Directory.CreateDirectory(路径);
}
尝试
{
while(fileCounter=BANS_PER_文件)
{
字符串文件名=string.Format(“{0}-{1}”,部分[0],部分[part.Count-1]);
string outputToFile=“;//否则您将看不到文件中的行。只显示一行!!
WriteLine(“NR{0}”,文件名);
string subString=System.IO.Path.Combine(路径,“BankNumbers”);//需要添加,否则文件将不会存储在正确的文件夹中!!
文件名=子字符串+文件名;
foreach(var partBan部分)
{
控制台写入线(partBan);
outputToFile+=partBan+Environment.NewLine;//将行写入文件
}
System.IO.File.WriteAllText(文件名,输出文件);//写入文件系统。
部分。清除();
班斯孔特=0;
//System.IO.File.WriteAllText(文件名,part.ToString());
如果(++fileCounter>=MAX_文件)
打破
}
}
}
timer.Stop();
Console.WriteLine(计时器。已用时间。秒);
}
捕获(例外)
{
投掷;
}
System.Console.WriteLine(“按任意键退出”);
System.Console.ReadKey();
}

但这会产生8100万个银行账户记录,这些记录被80多个文件分开。但是我可以用线程加速进程吗?

你说的是加速一个进程,它的瓶颈很可能是文件写入速度。您无法真正有效地将写入单个磁盘的操作并行化

如果生成一个只负责fileIO的工作线程,您可能会看到速度略有提高。换句话说,创建一个缓冲区,让主线程将内容转储到其中,而另一个线程将其写入磁盘。这是经典的生产者/消费者动态。然而,我并不指望速度会有大的提高

还请记住,写入控制台会减慢速度,但您可以将其保留在主线程中,这样可能会很好。只需确保对缓冲区大小进行限制,并在缓冲区已满时让生产者线程挂起


编辑:还可以查看提供的链接L-Three,使用BufferedStream将是一种改进(可能会使消费者线程变得不必要)

您的过程可以分为两个步骤:

  • 生成帐户
  • 将帐户保存在文件中
  • 第一步可以并行完成,因为帐户之间没有依赖关系。也就是说,创建帐号时,您不必依赖帐号中的数据(因为它可能尚未创建)

    问题在于将数据写入文件。您不希望多个线程尝试访问和写入同一个文件。添加锁可能会使代码成为维护的噩梦。另一个问题是对文件的写入减慢了整个过程

    目前,在代码中,创建帐户和写入文件只需一个过程

    您可以尝试将这些过程分开。因此,首先创建所有帐户并将它们保存在某个集合中。这里可以安全地使用多线程。只有在创建了所有帐户后,才能保存它们

    改进保存过程需要更多的工作。您必须将所有帐户分成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.
        }
    
    public void CreateAndSaveAccounts()
    {
    列表帐户=this.CreateAccounts();
    //将帐户分成不同的批
    //当然,这个过程可以(也应该)自动化。
    列出单独的数据库中的帐户=
    新名单
    {
    accounts.GetRange(0,10000000),//第一批1000万
    accounts.GetRange(10000000,10000000),//第二批1000万
    accounts.GetRange(20000000,10000000)//第三批1000万
    // ...
    };
    //并行保存帐户
    并行。对于(0,accountsInSeparateBatches.Count,
    i=>
    {
    stringfilepath=string.Format(@“C:\file{0}”,i);
    此.SaveAccounts(accountsInSeparateBatches[i],filePath);
    }
    );
    }
    公共列表创建帐户()
    {
    //在此处创建帐户
    //并将其作为集合返回。
    //尽可能使用并行处理
    }
    公共无效存储帐户(列表帐户、字符串文件路径)
    {
    //将帐户保存到文件
    //该方法创建一个线程来执行该工作。
    }
    
    可能不会,不。不管怎样,都不客气