Nid*_*dhi 3 c# datatable multithreading
我刚刚开始学习线程的概念,我有点困在这个问题上,它让我疯狂......
我真正需要完成的事情 -
我在本地目录中有大约300个文本文件,需要针对特定值进行解析...在每个文本文件中找到这些"值"后,我需要将它们存储在数据库中.所以我遵循了简单的方法访问目录中的每个文本文件 - 解析并将结果值作为一行更新到本地DataTable,当我完成解析所有文件并将300行存储到DataTable时,我会对我的DataTable执行SQLBulkCopy数据库.这种方法工作正常,只需要大约10分钟来运行我的代码!
我现在想做什么 -
为每个文件创建一个新线程,并在任何给定时间将线程数保持在4以下...然后每个线程将解析整个文件并返回一行以更新本地DataTable
我被困的地方 - 我不明白如何更新从多个线程获取行的单个数据表...
相当一个解释不是..希望这里有人可以为此提出一个好主意......
谢谢,Nidhi
正如有人指出的那样,您需要仔细检查瓶颈的位置以及使用线程的原因.
通过转移到多个线程,您可以提高性能.但是,如果您使用每个线程更新相同的DataTable,则受到DataTable的限制.只有一个线程可以一次写入DataTable(您使用锁控制),因此您仍然可以从根本上按顺序处理.
另一方面,大多数数据库是为多个连接设计的,在多个线程上运行,并且已经为此目的进行了高度调整.如果您仍想使用多个线程:让每个线程都有自己的数据库连接,并进行自己的处理.
现在,根据正在进行的处理类型,您的瓶颈可能在于打开和处理文件,而不是在数据库更新中.
分裂的一种方法:
这些可以同时运行...数据库将不会更新,直到有更新的东西,并将在此期间等待.
这种方法让你真正知道谁在等谁.如果读取/处理文件部分很慢,请创建更多线程来执行此操作.如果插入数据库部分的速度很慢,请创建更多线程来执行此操作.队列只需要同步.
所以,伪代码:
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().
这不是最简单的例子,但我认为这是彻底的.您正在同步两个队列,并且需要确保每个队列在访问之前都已锁定.您将跟踪每个线程何时完成,并且您在线程之间编组数据,但从未使用队列进行多次处理.
希望有所帮助.