DataTable的线程安全曾经看过这个回答ADO.NETDataTable/DataRowThreadSafety,有些看不懂。尤其是[2]的文章看不懂。我需要使用什么样的包装?谁能举个例子?也看不懂作者说的级联锁和全锁是什么意思。请举个例子。DataTable根本不是为并发使用而设计的(尤其是在涉及任何类型的突变的情况下)。在我看来,这里理想的“包装器”是:基本上:改变问题。来自评论:代码如下:Parallel.ForEach(strings,str=>{DataRowrow;lock(table){row=table.NewRow();}MyParser.Parse(str,outrow);lock(table){table.Rows.Add(row)}});我只能希望outrow在这里是一个错字,因为这实际上不会导致它填充通过NewRow()创建的行,但是:如果你必须使用这个方法,你就不能使用NewRow,因为待处理的行有点共享。你最好的选择是:Parallel.ForEach(strings,str=>{object[]values=MyParser.Parse(str);lock(table){table.Rows.Add(values);}});上面重要的变化是锁覆盖了整个newrow过程。请注意,使用Parallel.ForEach时无法保证顺序,因此最终顺序不需要完全匹配(如果数据包含时间分量,这应该不是问题)。然而!我仍然认为您以错误的方式处理这个问题:要使并行性相关,它必须是非平凡的数据。如果您有重要数据,您真的不想将其缓冲在内存中。我强烈推荐做类似下面的事情,它在单线程上运行良好:;bcp.WriteToServer(阅读器);}...staticIEnumerableParseFile(stringpath){using(varreader=File.OpenText(path)){stringline;while((line=reader.ReadLine())!=null){yieldreturnnewLogRow{//TODO:从此处填充行};}}}...publicsealedclassLogRow{/*在这里定义你的模式*/}奖励:我在自己的工作中这样做了很多事情,比如^^^,根据经验,它通常至少是填充的速度的两倍内存中的DataTable优先。最后-这是一个IEnumerable实现的示例,它接受并发的读取器和写入器而不在内存中缓存所有内容-这将允许多个线程使用SqlBulkCopy的单个线程(调用添加并最终关闭)通过IEnumerableAPI解析数据:上面以上就是C#学习教程的全部内容:DataTable的线程安全分享。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注——usingSystem;使用系统集合;使用System.Threading;使用System.Threading.Tasks;//////充当并发读/写刷新的容器(例如,在同时上传内容的同时解析///文件);支持任意数量的并发///作者和读者,但请注意,每个项目只会返回一次(一旦///获取,将被丢弃)。有必要在添加最后一个///数据后关闭()桶,否则任何迭代器将永远不会完成///classThreadSafeBucket:IEnumerable{privatereadonlyQueuequeue=newQueue();publicvoidAdd(Tvalue){lock(queue){if(closed)//关闭后没有更多数据thrownewInvalidOperationException("桶已被标记为关闭");queue.Enqueue(value);if(queue.Count==1){//有人可能正在等待数据Monitor.PulseAll(queue);}}}publicvoidClose(){lock(queue){closed=true;Monitor.PulseAll(queue);}}privateboolclosed;publicIEnumeratorGetEnumerator(){while(true){Tvalue;lock(queue){if(queue.Count==0){//没有数据;我们应该期待任何数据吗?if(closed)yieldbreak;//没有更多的东西//否则等待被唤醒,并从头开始重做Monitor.Wait(queue);continue;}value=queue.Dequeue();}//yieldit**outside**ofthelockyieldreturnvalue;}}IEnumeratorIEnumerable.GetEnumerator(){returnGetEnumerator();}}staticclassProgram{staticvoidMain(){varbucket=newThreadSafeBucket();intexpectedTotal=0;ThreadPool.QueueUserWorkItem(delegate{intcount=0,sum=0;foreach(variteminbucket){count++;sum+=item;if((count%100)==0)Console.WriteLine("{0}之后:{1}",cou新台币,总和);}Console.WriteLine("总计超过{0}:{1}",count,sum);});Parallel.For(0,5000,newParallelOptions{MaxDegreeOfParallelism=3},i=>{bucket.Add(i);Interlocked.Add(refexpectedTotal,i);});Console.WriteLine("所有数据已添加;关闭存储桶");bucket.Close();线程.睡眠(100);Console.WriteLine("预期总数:{0}",Interlocked.CompareExchange(refexpectedTotal,0,0));控制台.ReadLine();}}本文收集自网络,不代表立场。如涉及侵权请点击维权联系管理员删除如需转载请注明出处:
