多个线程将其结果填充到一个 DataTable C# 中

2024-05-11

我刚刚开始学习线程的概念,我有点陷入这个问题,它让我发疯......

我实际上需要完成什么 -

我在本地目录中有大约 300 个文本文件,需要解析它们以获取特定值...在每个文本文件中找到这些“值”后,我需要将它们存储在数据库中。 因此,我遵循访问目录中每个文本文件的简单方法 - 将结果值作为一行解析并更新到本地 DataTable,当我解析完所有文件并将 300 行存储到 DataTable 时,我会这样做DataTable 的 SQLBulkCopy 到我的数据库。这种方法效果很好,只是运行代码需要大约 10 分钟!

我现在正在尝试做的事情 -

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

我陷入困境 - 我不明白如何更新这个从多个线程获取行的单个数据表......

这是一个很好的解释不是吗..希望这里有人能为此提出一个好主意......

谢谢, 尼迪


正如有人指出的那样,您需要准确检查瓶颈在哪里以及为什么要使用线程。

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

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

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

一种拆分方法:

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

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

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

所以,伪代码:

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; }
   }
}

我很确定有办法让它变得“更好”,但它应该可以解决问题,这样您就可以读取和处理数据,同时将完整的数据添加到数据库中,并利用线程。

如果您希望另一个线程处理文件或更新数据库,只需创建一个新线程( MethodName ),然后调用 Start() 即可。

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

希望有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多个线程将其结果填充到一个 DataTable C# 中 的相关文章

随机推荐