多个线程将其结果填入一个DataTable C#

Nid*_*dhi 3 c# datatable multithreading

我刚刚开始学习线程的概念,我有点困在这个问题上,它让我疯狂......

我真正需要完成的事情 -

我在本地目录中有大约300个文本文件,需要针对特定​​值进行解析...在每个文本文件中找到这些"值"后,我需要将它们存储在数据库中.所以我遵循了简单的方法访问目录中的每个文本文件 - 解析并将结果值作为一行更新到本地DataTable,当我完成解析所有文件并将300行存储到DataTable时,我会对我的DataTable执行SQLBulkCopy数据库.这种方法工作正常,只需要大约10分钟来运行我的代码!

我现在想做什么 -

为每个文件创建一个新线程,并在任何给定时间将线程数保持在4以下...然后每个线程将解析整个文件并返回一行以更新本地DataTable

我被困的地方 - 我不明白如何更新从多个线程获取行的单个数据表...

相当一个解释不是..希望这里有人可以为此提出一个好主意......

谢谢,Nidhi

Jon*_*hem 6

正如有人指出的那样,您需要仔细检查瓶颈的位置以及使用线程的原因.

通过转移到多个线程,您可以提高性能.但是,如果您使用每个线程更新相同的DataTable,则受到DataTable的限制.只有一个线程可以一次写入DataTable(您使用锁控制),因此您仍然可以从根本上按顺序处理.

另一方面,大多数数据库是为多个连接设计的,在多个线程上运行,并且已经为此目的进行了高度调整.如果您仍想使用多个线程:让每个线程都有自己的数据库连接,并进行自己的处理.

现在,根据正在进行的处理类型,您的瓶颈可能在于打开和处理文件,而不是在数据库更新中.

分裂的一种方法:

  1. 将要处理的所有文件名放入文件名Queue中.
  2. 创建一个线程(或多个线程)以从文件名Queue中提取项目,打开并解析并处理该文件,并将结果推送到结果队列中.
  3. 让另一个线程从结果Queue中获取结果,并将它们插入到数据库中.

这些可以同时运行...数据库将不会更新,直到有更新的东西,并将在此期间等待.

这种方法让你真正知道谁在等谁.如果读取/处理文件部分很慢,请创建更多线程来执行此操作.如果插入数据库部分的速度很慢,请创建更多线程来执行此操作.队列只需要同步.

所以,伪代码:

Queue<string> _filesToProcess = new Queue<string>();
Queue<string> _results = new Queue<string>();
Thread _fileProcessingThread = new Thread( ProcessFiles );
Thread _databaseUpdatingThread = new Thread( UpdateDatabase );
bool _finished = false;

static void Main()
{
    foreach( string fileName in GetFileNamesToProcess() )
    {
       _filesToProcess.Enqueue( fileName );
    }

    _fileProcessingThread.Start();
    _databaseUpdatingThread.Start();

    // if we want to wait until they're both finished
    _fileProcessingThread.Join();
    _databaseUpdatingThread.Join();

    Console.WriteLine( "Done" );
}

void ProcessFiles()
{
   bool filesLeft = true;

   lock( _filesToProcess ){ filesLeft = _filesToProcess.Count() > 0; }

   while( filesLeft )
   {
      string fileToProcess;
      lock( _filesToProcess ){ fileToProcess = _filesToProcess.Dequeue(); }

      string resultAsString = ProcessFileAndGetResult( fileToProcess );

      lock( _results ){ _results.Enqueue( resultAsString ); }

      Thread.Sleep(1); // prevent the CPU from being 100%

      lock( _filesToProcess ){ filesLeft = _filesToProcess.Count() > 0; }
   }

   _finished = true;
}

void UpdateDatabase()
{
   bool pendingResults = false;

   lock( _results ){ pendingResults = _results.Count() > 0; }

   while( !_finished || pendingResults )
   {
      if( pendingResults )
      {
         string resultsAsString;
         lock( _results ){ resultsAsString = _results.Dequeue(); }

         InsertIntoDatabase( resultsAsString ); // implement this however
      }

      Thread.Sleep( 1 ); // prevents the CPU usage from being 100%

      lock( _results ){ pendingResults = _results.Count() > 0; }
   }
}
Run Code Online (Sandbox Code Playgroud)

我很确定有什么方法可以让它"更好",但它应该可以解决这个问题,这样你就可以读取和处理数据,同时还可以将完整的数据添加到数据库中,并利用线程.

如果您希望另一个Thread处理文件或更新数据库,只需创建一个新的Thread(MethodName),然后调用Start().

这不是最简单的例子,但我认为这是彻底的.您正在同步两个队列,并且需要确保每个队列在访问之前都已锁定.您将跟踪每个线程何时完成,并且您在线程之间编组数据,但从未使用队列进行多次处理.

希望有所帮助.