当前位置: 首页 > 编程语言 > C#

多线程将结果填入一个DataTableC#分享

时间:2023-04-10 13:51:12 C#

疯狂...我真正需要完成的事情-我在本地目录中有大约300个文本文件需要解析特定值...之后在每个文本文件中找到这些“值”,我需要将它们存储在数据库中。因此,我遵循了访问目录中每个文本文件的简单方法——将结果值作为一行解析并更新到本地DataTable,当我解析完所有文件并将300行存储到DataTable后,我执行SQLBulkCopy数据库。这种方法工作正常,但运行我的代码大约需要10分钟!我现在想做的-为每个文件创建一个新线程,并在任何给定时间将线程数保持在4以下......然后每个线程将解析整个文件并返回一行以更新我所在的本地数据表卡住-我不明白如何更新从多个线程获取行的单个数据表......很好的解释不......希望这里有人能为此想出一个好主意......谢谢,Nidhi如果你让每个四个线程自己写进数据库,会比较容易。在这种情况下,您不必担心线程(每个线程处理的文件除外),因为每个工作线程都可以维护自己的数据表并占用25%的文件。或者,您可以拥有一个所有线程都使用的数据表-只需确保用锁包装对它的访问:lock(YourTable.Rows.SyncRoot){//addrowstotable}当然,如果瓶颈是磁盘,正如@DavidB所说,根本没有。正如有人指出的那样,您需要准确检查瓶颈在哪里以及为什么要使用线程。您确实有可能通过转向多线程来提高性能。但是,如果使用每个线程更新同一个DataTable,就会受到DataTable的限制。一次只有一个线程可以写入DataTable(您用锁控制),因此您仍然可以从根本上按顺序进行处理。另一方面,大多数数据库都是为多连接而设计的,在多线程上运行,并且已经为此目的进行了高度调整。如果您仍想使用多线程:让每个线程都有自己的数据库连接,并进行自己的处理。现在,根据正在进行的处理类型,您的瓶颈可能在于打开和处理文件,而不是数据库更新。一种拆分方式:将所有需要处理的文件名放入一个文件名队列中。创建一个线程(或多个线程)从文件名队列中拉取项目,打开并解析和处理文件,并将结果推送到结果队列。让另一个线程从结果队列中获取结果,并将它们插入到数据库中。这些可以同时运行......数据库不会更新,直到有更新的东西,并同时等待。这种方法让您真正知道谁在等谁。如果读取/处理文件的某些部分很慢,请创建更多的多线程来执行此操作。如果插入数据库部分很慢,请创建更多的多线程来完成它。队列只需要同步。所以,伪代码:Queue_filesToProcess=newQueue();队列_results=新队列();线程_fileProcessingThread=newThread(ProcessFiles);Thread_databaseUpdatingThread=newThread(更新数据库);布尔_finished=假;staticvoidMain(){foreach(StringfileNameinGetFileNamesToProcess()){_filesToProcess.Enqueue(fileName);}_fileProcessingThread.Start();_databaseUpdatingThread.Start();//如果我们想等到它们都完成_fileProcessingThread.Join();_databaseUpdatingThread.Join();Console.WriteLine("完成");}voidProcessFiles(){boolfilesLeft=true;锁(_filesToProcess){filesLeft=_filesToProcess.Count()>0;}while(filesLeft){stringfileToProcess;锁(_filesToProcess){fileToProcess=_filesToProcess.Dequeue();}stringresultAsString=ProcessFileAndGetResult(fileToProcess);锁(_results){_results.Enqueue(resultAsString);}Thread.Sleep(1);//防止CPU被100%lock(_filesToProcess){filesLeft=_filesToProcess.Count()>0;}}_finished=真;}voidUpdateDatabase(){boolpendingResults=false;锁(_results){pendingResults=_results.Count()>0;}while(!_finished||pendingResults){if(pendingResults){stringresultsAsString;锁(_results){resultsAsString=_results.Dequeue();}InsertIntoDatabase(resultsAsString);//然而实现这个}Thread.Sleep(1);//防止CPU使用率达到100%lock(_results){pendingResults=_results.Count()>0;我很确定有一些东西可以让它“更好”,但它应该解决这个问题,这样你就可以读取和处理数据,同时还可以将完整的数据添加到数据库中,并利用线程如果你想要另一个线程来处理文件或更新数据库,只需创建一个新线程(MethodName),然后调用Start()。这不是最简单的例子,但我认为它很彻底。您正在同步两个队列,您需要确保每个队列在被访问之前都已锁定。您正在跟踪每个线程何时完成,并且在线程之间编组数据,但从不使用队列进行多重处理。希望有所帮助。是什么让您认为更多的线程会改善事情?他们可能不会。我建议你先让程序运行起来,然后再考虑让它运行得更快。只需使用一个线程。SQLBulkCopy是一个只有300行的大锤。查看智能线程池。这是一个实例线程池,您可以非常轻松地将其限制为4个线程。由于您只有300行,请考虑将它们直接发布到每个线程中的SQL,而不是在代码中聚合。正如其他人指出的那样,请记住在更新之前锁定您的表格。C#:私有对象表锁;/*稍后在代码中。*/privatevoidUpdateDataTable(objectdata){lock(tableLock){//Addorupdatetablerows}}至于实际控制和保持线程的方法,只需要使用ThreadPool对象,设置最大线程限制,队列就可以搞定.对于其他控件,可以使用WaitHandle对象数组来处理一些逻辑。事实上,考虑到您要对300个单独的对象进行排队,这可能是个好主意。以上就是C#学习教程:多个线程将自己的结果填充到一个DataTable中。C#分享的所有内容,如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注——本文来自网络收集,不代表立场,如涉及侵权,请点击维权联系管理员删除。如需转载请注明出处: