C# 使用TPL的生产者-消费者模型.NET4.0中的任务
我有一个相当大的XML文件(大约1-2GB) 需求是将xml数据持久化到数据库中。 目前,这是通过3个步骤实现的C# 使用TPL的生产者-消费者模型.NET4.0中的任务,c#,multithreading,.net-4.0,task-parallel-library,C#,Multithreading,.net 4.0,Task Parallel Library,我有一个相当大的XML文件(大约1-2GB) 需求是将xml数据持久化到数据库中。 目前,这是通过3个步骤实现的 尽可能用更少的内存足迹读取大文件 从xml数据创建实体 使用SqlBulkCopy将创建的实体中的数据存储到数据库中 为了获得更好的性能,我想创建一个生产者-消费者模型,生产者在该模型中创建一组实体,比如说一批10K,并将其添加到队列中。使用者应该从队列中取出一批实体,并使用sqlbulkcopy持久化到数据库 谢谢, 戈库尔 void Main() { int-iCount=0;
void Main()
{
int-iCount=0;
字符串文件名=@“C:\Data\CatalogIndex.xml”;
DateTime startTime=DateTime.Now;
WriteLine(“开始时间:{0}”,开始时间);
FileInfo fi=新的FileInfo(文件名);
WriteLine(“文件大小:{0}MB”,fi.Length/1048576.0);
/*我想改变这个循环,在这里创建生产者-消费者模式,并行地处理数据
*/
foreach(StreamElements中的var元素(文件名,“title”))
{
iCount++;
}
WriteLine(“计数:{0}”,iCount);
WriteLine(“结束时间:{0},花费的时间:{1}”,DateTime.Now,DateTime.Now-startTime);
}
私有静态IEnumerable流元素(字符串文件名、字符串元素名)
{
使用(var rdr=XmlReader.Create(文件名))
{
rdr.MoveToContent();
而(!rdr.EOF)
{
if((rdr.NodeType==XmlNodeType.Element)和&(rdr.Name==elementName))
{
var e=XElement.ReadFrom(rdr)作为XElement;
收益率e;
}
其他的
{
rdr.Read();
}
}
rdr.Close();
}
}
这就是你想要做的吗
void Main()
{
const int inputCollectionBufferSize = 1024;
const int bulkInsertBufferCapacity = 100;
const int bulkInsertConcurrency = 4;
BlockingCollection<object> inputCollection = new BlockingCollection<object>(inputCollectionBufferSize);
Task loadTask = Task.Factory.StartNew(() =>
{
foreach (object nextItem in ReadAllElements(...))
{
// this will potentially block if there are already enough items
inputCollection.Add(nextItem);
}
// mark this collection as done
inputCollection.CompleteAdding();
});
Action parseAction = () =>
{
List<object> bulkInsertBuffer = new List<object>(bulkInsertBufferCapacity);
foreach (object nextItem in inputCollection.GetConsumingEnumerable())
{
if (bulkInsertBuffer.Length == bulkInsertBufferCapacity)
{
CommitBuffer(bulkInsertBuffer);
bulkInsertBuffer.Clear();
}
bulkInsertBuffer.Add(nextItem);
}
};
List<Task> parseTasks = new List<Task>(bulkInsertConcurrency);
for (int i = 0; i < bulkInsertConcurrency; i++)
{
parseTasks.Add(Task.Factory.StartNew(parseAction));
}
// wait before exiting
loadTask.Wait();
Task.WaitAll(parseTasks.ToArray());
}
void Main()
{
常量int inputCollectionBufferSize=1024;
常量int bulkInsertBufferCapacity=100;
常量int bulkInsertConcurrency=4;
BlockingCollection inputCollection=新BlockingCollection(inputCollectionBufferSize);
Task loadTask=Task.Factory.StartNew(()=>
{
foreach(读取中的对象nextItem(…)
{
//如果已经有足够的项目,这可能会阻塞
inputCollection.Add(nextItem);
}
//将此集合标记为已完成
inputCollection.CompleteAdding();
});
动作语法动作=()=>
{
List bulkInsertBuffer=新列表(bulkInsertBufferCapacity);
foreach(inputCollection.GetConsumingEnumerable()中的对象nextItem)
{
if(bulkInsertBuffer.Length==bulkInsertBufferCapacity)
{
CommitBuffer(bulkInsertBuffer);
bulkInsertBuffer.Clear();
}
bulkInsertBuffer.Add(nextItem);
}
};
List parseTasks=新列表(bulkInsertConcurrency);
for(int i=0;i
这就是你想要做的吗
void Main()
{
const int inputCollectionBufferSize = 1024;
const int bulkInsertBufferCapacity = 100;
const int bulkInsertConcurrency = 4;
BlockingCollection<object> inputCollection = new BlockingCollection<object>(inputCollectionBufferSize);
Task loadTask = Task.Factory.StartNew(() =>
{
foreach (object nextItem in ReadAllElements(...))
{
// this will potentially block if there are already enough items
inputCollection.Add(nextItem);
}
// mark this collection as done
inputCollection.CompleteAdding();
});
Action parseAction = () =>
{
List<object> bulkInsertBuffer = new List<object>(bulkInsertBufferCapacity);
foreach (object nextItem in inputCollection.GetConsumingEnumerable())
{
if (bulkInsertBuffer.Length == bulkInsertBufferCapacity)
{
CommitBuffer(bulkInsertBuffer);
bulkInsertBuffer.Clear();
}
bulkInsertBuffer.Add(nextItem);
}
};
List<Task> parseTasks = new List<Task>(bulkInsertConcurrency);
for (int i = 0; i < bulkInsertConcurrency; i++)
{
parseTasks.Add(Task.Factory.StartNew(parseAction));
}
// wait before exiting
loadTask.Wait();
Task.WaitAll(parseTasks.ToArray());
}
void Main()
{
常量int inputCollectionBufferSize=1024;
常量int bulkInsertBufferCapacity=100;
常量int bulkInsertConcurrency=4;
BlockingCollection inputCollection=新BlockingCollection(inputCollectionBufferSize);
Task loadTask=Task.Factory.StartNew(()=>
{
foreach(读取中的对象nextItem(…)
{
//如果已经有足够的项目,这可能会阻塞
inputCollection.Add(nextItem);
}
//将此集合标记为已完成
inputCollection.CompleteAdding();
});
动作语法动作=()=>
{
List bulkInsertBuffer=新列表(bulkInsertBufferCapacity);
foreach(inputCollection.GetConsumingEnumerable()中的对象nextItem)
{
if(bulkInsertBuffer.Length==bulkInsertBufferCapacity)
{
CommitBuffer(bulkInsertBuffer);
bulkInsertBuffer.Clear();
}
bulkInsertBuffer.Add(nextItem);
}
};
List parseTasks=新列表(bulkInsertConcurrency);
for(int i=0;i
我尝试使用线程本地存储,但到目前为止,我只使用单线程方法,即调用一个方法来创建实体,然后同步保存它们。我尝试使用线程本地存储,但到目前为止,我只使用了一种单线程方法,即只调用一个方法来创建实体,然后同步保存它们。这是一个良好的开端。如何使CommitBuffer方法在X个线程中并行执行。由于在一个耗时的操作中将数据持久化到数据库中,我希望将其作为一个具有可配置线程数的多线程操作来执行。我将尝试实现此代码并在此处更新。@user943141-这不会有多大区别。如果确实需要,可以多次启动parseTasks。然而,数据库操作是一项繁重且可靠的操作。您可能只会使用多个线程来降低速度,因为IO是瓶颈,并且