C# 使用TPL的生产者-消费者模型.NET4.0中的任务

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;

我有一个相当大的XML文件(大约1-2GB)

需求是将xml数据持久化到数据库中。 目前,这是通过3个步骤实现的

  • 尽可能用更少的内存足迹读取大文件
  • 从xml数据创建实体
  • 使用SqlBulkCopy将创建的实体中的数据存储到数据库中 为了获得更好的性能,我想创建一个生产者-消费者模型,生产者在该模型中创建一组实体,比如说一批10K,并将其添加到队列中。使用者应该从队列中取出一批实体,并使用sqlbulkcopy持久化到数据库

    谢谢, 戈库尔

    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是瓶颈,并且