多线程,阅读与计算分开 [英] Multithreading, reading seperated from calculating

查看:81
本文介绍了多线程,阅读与计算分开的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,



此程序计算9位数的所有银行帐号。并将所有银行帐号写入文件系统。有82个文件,每个文件有大约1000 000条记录(行)。但是如何分离计算银行帐号和用多线程写入文件系统。我这样想:



我有这个:



  public   class 计划
{
public int id;
public 程序( int _id)
{
this .id = _id;

}

静态 void Main(< span class =code-keyword> string [] args)
{

string path = @ C:\ BankNumber;
var bans = BankAcoutNumbers.BANS;
const int MAX_FILES = 82 ;
const int BANS_PER_FILE = 81818182 / 82 ;
int bansCounter = 0 ;
var part = new List< int>();
var maxNumberOfFiles = 10 ;
秒表计时器= 秒表();
var fileCounter = 0 ;





if (!Directory.Exists(path))
{
DirectoryInfo di = Directory.CreateDirectory(path);
}

尝试
{
,而(fileCounter < = maxNumberOfFiles)
{
timer.Start();
Console.WriteLine( 开始将银行编号写入文件系统);
// Console.WriteLine(timer.Start());
< span class =code-keyword> foreach ( var bank in BankAcoutNumbers.BANS)
{
part.Add(bank);
if (++ bansCounter > = BANS_PER_FILE)
{
string fileName = string .Format( {0} .txt- {1} .txt,part [ 0 ],part [part .Count - 1 ]);
// string outputToFile =; //否则你看不到文件中的行。只需一行!!
StringBuilder OutputFile = new StringBuilder( );


string subString = System.IO.Path.Combine(path, nr); // 需要添加,因为否则文件将不会存储在正确的文件夹中!!
fileName = subString + fileName;

foreach var partBan in part)
{
OutputFile.Append( string .Format( {0} {1},partBan.ToString(),Environment.NewLine));


}
// 写入文件系统。
System.IO.File.WriteAllText(fileName,OutputFile.ToString());
part.Clear();
bansCounter = 0 ;
ThreadPool.QueueUserWorkItem(DoLongTask);


if (++ fileCounter > = MAX_FILES)
break ;
}
}
}

timer.Stop();
Console.WriteLine( 将银行编号写入文件系统的总时间 + timer .Elapsed.TotalSeconds + seconds);
// Console.WriteLine(BankAcoutNumbers.BANS.Count());
}
catch (例外)
{

throw ;
}
// Console.WriteLine(主要线程结束);
System.Console.WriteLine( 按任意键退出。 );
System.Console.ReadKey();
}

public static void DoLongTask( object 输入)
{
// int index =(int)input;
Console.WriteLine( 创建的文件:{0},Thread.CurrentThread.IsAlive);
}

} < / int >





谢谢





oke,我这样试试:





  public   class 计划
{
public int id;
静态列表< int> part = new List< int>();
static int bansCounter = 0 ;
const int BANS_PER_FILE = 81818182 / 82 ;
static string path = @ C:\ BankNumber;
const int MAX_FILES = 82 ;

静态 int fileCounter = 0 ;
static ReaderWriterLockSlim _rw = new ReaderWriterLockSlim();
// public Program(int _id)
// {
// this.id = _id;

// }


静态 void Main( string [] args)
{
if (!Directory.Exists(path))
{
DirectoryInfo di = Directory.CreateDirectory(path);
}

new 线程(读取).Start();
new 线程(读取).Start();
new 线程(读取).Start();

new 线程(写入).Start( A);
new 线程(写入).Start( B);


var bans = BankAcoutNumbers.BANS;
System.Console.WriteLine( 按任意键退出。);
System.Console.ReadKey();

}

静态 void 读取()
{
while true
{
_rw.EnterReadLock();
foreach int i in 部分)Thread.Sleep( 10 );
_rw.ExitReadLock();
}
}

静态 void 写( object threadID)
{
while true
{

foreach var bank in BankAcoutNumbers.BANS)
{
part.Add(bank);
if (++ bansCounter > = BANS_PER_FILE)
{
string fileName = string .Format( {0} .txt- {1} .txt,part [ 0 ],part [part .Count - 1 ]);
// string outputToFile =; //否则你看不到文件中的行。只需一行!!
StringBuilder OutputFile = new StringBuilder( );


string subString = System.IO.Path.Combine(path, nr); // 需要添加,因为否则文件将不会存储在正确的文件夹中!!
fileName = subString + fileName;

foreach var partBan in part)
{
OutputFile.Append( string .Format( {0} {1},partBan.ToString(),Environment.NewLine));


}
// 写入文件系统。
System.IO.File.WriteAllText(fileName,OutputFile.ToString());
part.Clear();
bansCounter = 0 ;
// ThreadPool.QueueUserWorkItem(DoLongTask);


if (++ fileCounter > = MAX_FILES)
断裂;
}

_rw.EnterWriteLock();
_rw.ExitWriteLock();
Console.WriteLine( Thread + threadID + 添加 + part);
Thread.Sleep( 100 );
}
}
}


}







但是我收到了这个错误:



附加信息:收集已被修改;枚举操作可能无法执行。



这一行:



foreach(int i in part)主题.Sleep(10);

解决方案

听起来像生产者 - 消费者。使用c#5.0,您可以使用async / await。看一下这个链接的例子:

https://msdn.microsoft.com/en-us/library/hh228601%28v=vs.110%29.aspx [ ^ ]



祝你好运!


你可以从非常简单的设计开始,如下面的伪代码,可以在以后添加多线程功能。



IBankManager

|

|列表与LT;串GT;计算()

| - > AccountNumberManager

|

|列表与LT;串GT;计算()



IOutputManager

|

| - >写(List< string>)

|

| - > FileOutputManager

- >写(List< string>)



  void  main()
{
IBankManager accountNumberManager = new AccountNumberManager()
IOutputManager fileManager = new FileOutputManager()
List< string> list = accountNumberManager.Calculate();
fileManager.Write(list);
} < / string > < /跨度>


Hi everybody,

This program calculates all the bank account numbers from 9 digits. and all the bank account numbers are written to the file system. There are 82 files and each file has around 1000 000 records(lines). But how to seperate the Calculating of the bank account numbers and the writing to the file system with multithreading. I am trying it like this:

I have this:

public class Program
    {
        public int id;
        public Program(int _id)
        {
            this.id = _id;

        }

        static void Main(string[] args)
        {

            string path = @"C:\BankNumber";
            var bans = BankAcoutNumbers.BANS;
            const int MAX_FILES = 82;
            const int BANS_PER_FILE = 81818182 / 82;
            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();
                    Console.WriteLine("Start writing the bank numbers to file system");
                    // Console.WriteLine(timer.Start());
                    foreach (var bank in BankAcoutNumbers.BANS)
                    {
                        part.Add(bank);
                        if (++bansCounter >= BANS_PER_FILE)
                        {
                            string fileName = string.Format("{0}.txt-{1}.txt", part[0], part[part.Count - 1]);
                            //string outputToFile = "";// Otherwise you dont see the lines in the file. Just single line!!
                            StringBuilder OutputFile = new StringBuilder("");


                            string subString = System.IO.Path.Combine(path, "nr");//Needed to add, because otherwise the files will not stored in the correct folder!!
                            fileName = subString + fileName;

                            foreach (var partBan in part)
                            {
                                OutputFile.Append(string.Format("{0}{1}", partBan.ToString(), Environment.NewLine));


                            }
                            //Writes to file system.
                            System.IO.File.WriteAllText(fileName, OutputFile.ToString());
                            part.Clear();
                            bansCounter = 0;
                            ThreadPool.QueueUserWorkItem(DoLongTask);


                            if (++fileCounter >= MAX_FILES)
                                break;
                        }
                    }
                }

                timer.Stop();
                Console.WriteLine("Total time of writing the bank numbers to file system " + timer.Elapsed.TotalSeconds + " seconds");
                //Console.WriteLine(BankAcoutNumbers.BANS.Count());
            }
            catch (Exception)
            {

                throw;
            }
            //Console.WriteLine("Main thread ends");            
            System.Console.WriteLine("Press any key to exit.");
            System.Console.ReadKey();
        }

        public static void DoLongTask(object input)
        {
            //int index = (int)input;
            Console.WriteLine("Created file : {0}", Thread.CurrentThread.IsAlive);
        }

    }</int>



Thank you


oke, I try it like this:


public class Program
    {
        public int id;
        static List<int> part = new List<int>();
        static int bansCounter = 0;
        const int BANS_PER_FILE = 81818182 / 82;
        static string path = @"C:\BankNumber";
        const int MAX_FILES = 82;
         
        static int fileCounter = 0;
        static ReaderWriterLockSlim _rw = new ReaderWriterLockSlim();
        //public Program(int _id)
        //{
        //    this.id = _id;

        //}


        static void Main(string[] args)
        {
            if (!Directory.Exists(path))
            {
                DirectoryInfo di = Directory.CreateDirectory(path);
            }

            new Thread(Read).Start();
            new Thread(Read).Start();
            new Thread(Read).Start();

            new Thread(Write).Start("A");
            new Thread(Write).Start("B");


            var bans = BankAcoutNumbers.BANS;
            System.Console.WriteLine("Press any key to exit.");
            System.Console.ReadKey();

        }

        static void Read()
        {
            while (true)
            {
                _rw.EnterReadLock();
                foreach (int i in part ) Thread.Sleep(10);
                _rw.ExitReadLock();
            }
        }

        static void Write(object threadID)
        {
            while (true)
            {

                foreach (var bank in BankAcoutNumbers.BANS)
                {
                    part.Add(bank);
                    if (++bansCounter >= BANS_PER_FILE)
                    {
                        string fileName = string.Format("{0}.txt-{1}.txt", part[0], part[part.Count - 1]);
                        //string outputToFile = "";// Otherwise you dont see the lines in the file. Just single line!!
                        StringBuilder OutputFile = new StringBuilder("");


                        string subString = System.IO.Path.Combine(path, "nr");//Needed to add, because otherwise the files will not stored in the correct folder!!
                        fileName = subString + fileName;

                        foreach (var partBan in part)
                        {
                            OutputFile.Append(string.Format("{0}{1}", partBan.ToString(), Environment.NewLine));


                        }
                        //Writes to file system.
                        System.IO.File.WriteAllText(fileName, OutputFile.ToString());
                        part.Clear();
                        bansCounter = 0;
                        //ThreadPool.QueueUserWorkItem(DoLongTask);


                        if (++fileCounter >= MAX_FILES)
                            break;
                    }

                _rw.EnterWriteLock();              
                _rw.ExitWriteLock();
                Console.WriteLine("Thread " + threadID + " added " + part);
                Thread.Sleep(100);
                }            
            }
        }

      
    }




But I get this error:

Additional information: Collection was modified; enumeration operation may not execute.

on this line:

foreach (int i in part ) Thread.Sleep(10);

解决方案

Sounds like producer-consumer. Using c#5.0 you can utilize async/await. Have a look at this link for an example:
https://msdn.microsoft.com/en-us/library/hh228601%28v=vs.110%29.aspx[^]

Good luck!


You can start with very simple design like below pseudo code and can add multi-threaded capabilities later.

IBankManager
|
| List<string> Calculate()
|->AccountNumberManager
|
| List<string> Calculate()

IOutputManager
|
|-> Write(List<string>)
|
|->FileOutputManager
-> Write(List<string>)

void main()
{
   IBankManager accountNumberManager = new AccountNumberManager()
   IOutputManager fileManager = new FileOutputManager()
   List<string> list =  accountNumberManager.Calculate();
   fileManager.Write( list );
}</string>


这篇关于多线程,阅读与计算分开的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆