- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
希望大家多多包涵。我想提供尽可能多的信息。主要问题是如何创建一个将由多个线程使用的结构(如堆栈),这些线程将弹出一个值并使用它来处理一个大的平面文件,并可能一次又一次地循环直到整个文件被处理。如果一个文件有 100.000 条记录,可以由 5 个线程使用 2.000 行 block 处理然后每个线程将得到 10 个 block 来处理。
我的目标是移动平面文件中的数据(带有 Header...Subheader...Detail、Detail、Detail、...Detail、SubFooter、Subheader...Detail、Detail、Detail、...Detail , 子页脚,Subheader...Detail, Detail, Detail, ...Detail, SubFooter, Footer structure) into OLTP DB that has recovery mode to Simple (possible Full) into 3 tables: 1st representing Subheader's unique key present in Subheader row, 第二个中间表 SubheaderGroup,表示 2000 条记录 block 中的详细信息行分组(需要将 Subheader 的标识 PK 作为其 FK,第三个表示 FK 指向 Subheader PK 的详细信息行。
我正在进行手动事务管理,因为我可以有数万个详细信息行我正在使用一个特殊字段,该字段在加载期间在目标表中设置为 0,然后在文件处理结束时我正在执行事务更新,将此值更改为 1,这可以向其他应用程序发出加载完成的信号。
我想将这个平面文件分成多个相等的部分(行数相同),这些部分可以用多个线程处理,并使用从目标表元数据创建的 IDataReader 使用 SqlBulkCopy 导入。
我想使用生产者/消费者模式(如以下链接中的解释 - pdf 分析和代码示例)来使用带有 SqlBulkCopyOptions.TableLock 选项的 SqlBulkCopy。 http://sqlblog.com/blogs/alberto_ferrari/archive/2009/11/30/sqlbulkcopy-performance-analysis.aspx此模式允许创建多个生产者,并且需要等量的消费者订阅生产者才能使用该行。
在TestSqlBulkCopy项目中,DataProducer.cs文件中有一个模拟产生数千条记录的方法。
public void Produce (DataConsumer consumer, int numberOfRows) {
int bufferSize = 100000;
int numberOfBuffers = numberOfRows / bufferSize;
for (int bufferNumber = 0; bufferNumber < numberOfBuffers; bufferNumber++) {
DataTable buffer = consumer.GetBufferDataTable ();
for (int rowNumber = 0; rowNumber < bufferSize; rowNumber++) {
object[] values = GetRandomRow (consumer);
buffer.Rows.Add (values);
}
consumer.AddBufferDataTable (buffer);
}
}
此方法将在新线程的上下文中执行。我希望这个新线程只读取一个独特的原始平面文件 block ,另一个线程将开始处理下一个 block 。然后,消费者将使用 SqlBulkCopy ADO.NET 类将数据(发送给他们的数据)移动到 SQL Server 数据库。
所以这里的问题是关于主程序规定每个线程应该处理 lineFrom 到 lineTo 的内容,我认为这应该在线程创建期间发生。第二种解决方案可能是线程共享一些结构并使用它们独有的东西(如线程号或序列号)来查找共享结构(可能是堆栈并弹出一个值(在执行时锁定堆栈)然后下一个线程将然后拾取下一个值。主程序将拾取平面文件并确定 block 的大小并创建堆栈。
那么有人可以提供一些代码片段,关于多个线程如何处理一个文件并且只获取该文件的唯一部分的伪代码吗?
谢谢,拉德
最佳答案
对我来说效果最好的是使用队列来保存未处理的工作,并使用字典来跟踪进行中的工作:
作为控制台应用程序的演示代码:
using System;
using System.Collections.Generic;
using System.Threading;
namespace threadtest
{
public delegate void DoneCallbackDelegate(int idArg, bool successArg, string messageArg);
class Program
{
static void Main(string[] args)
{
Supervisor supv = new Supervisor();
supv.LoadQueue();
supv.Dispatch();
}
}
public class Supervisor
{
public Queue<Worker> pendingWork = new Queue<Worker>();
public Dictionary<int, Worker> activeWork = new Dictionary<int, Worker>();
private object pendingLock = new object();
private object activeLock = new object();
private int maxThreads = 200;
public void LoadQueue()
{
for (int i = 0; i < 1000; i++)
{
Worker worker = new Worker();
worker.Callback = new DoneCallbackDelegate(WorkerFinished);
lock (pendingLock)
{
pendingWork.Enqueue(worker);
}
}
}
public void Dispatch()
{
int activeThreadCount;
while (true)
{
lock (activeLock) { activeThreadCount = activeWork.Count; }
while (true)
{
lock (activeLock)
{
if (activeWork.Count == maxThreads) break;
}
lock (pendingWork)
{
if (pendingWork.Count > 0)
{
Worker worker = pendingWork.Dequeue();
Thread thread = new Thread(new ThreadStart(worker.DoWork));
thread.IsBackground = true;
worker.ThreadId = thread.ManagedThreadId;
lock (activeLock) { activeWork.Add(worker.ThreadId, worker); }
thread.Start();
}
else
{
break;
}
}
}
Thread.Sleep(200); // wait to see if any workers are done (many ways to do this)
lock (pendingLock)
lock (activeLock)
{
if ((pendingWork.Count == 0) && (activeWork.Count == 0)) break;
}
}
}
// remove finished threads from activeWork, resubmit if necessary, and update UI
public void WorkerFinished(int idArg, bool successArg, string messageArg)
{
lock (pendingLock)
lock (activeLock)
{
Worker worker = activeWork[idArg];
activeWork.Remove(idArg);
if (!successArg)
{
// check the message or something to see if you should resubmit thread
pendingWork.Enqueue(worker);
}
// update UI
int left = Console.CursorLeft;
int top = Console.CursorTop;
Console.WriteLine(string.Format("pending:{0} active:{1} ", pendingWork.Count, activeWork.Count));
Console.SetCursorPosition(left, top);
}
}
}
public class Worker
{
// this is where you put in your problem-unique stuff
public int ThreadId { get; set; }
DoneCallbackDelegate callback;
public DoneCallbackDelegate Callback { set { callback = value; } }
public void DoWork()
{
try
{
Thread.Sleep(new Random().Next(500, 5000)); // simulate some effort
callback(ThreadId, true, null);
}
catch (Exception ex)
{
callback(ThreadId, false, ex.ToString());
}
}
}
}
关于c# - 使用生产者/消费者模式和 SqlBulkCopy 将平面文件分块处理到 SQL Server 数据库中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2066503/
在 .Net Aspx 页面或 Web 服务需要在表中执行大约 20-200 行插入的情况下,您会推荐以下哪种方法?为什么?小的性能提升可能意味着我仍然会使用我最熟悉的方法,所以请告诉我它是否不会产生
SqlBulkCopy可以创建一个类似于SELECT INTO的表吗? 最佳答案 我认为上述答案不太清楚。 您必须使用SQL创建表。没有别的办法了。而且,如果您只需要创建列结构,那么如果您的源代码位于
在我的程序中,我正在填充数据表,然后将其批量复制到我的数据库中。 但是,如果行中的 3 列匹配,我希望它覆盖数据库中的一行。 例如,如果我有 5 列 成员(member)编号注册日期姓名地址城市状态
我熟悉 C# SqlBulkCopy 类,您可以在其中调用通过 DataTable 传递的“WriteToServer”方法。 我的问题是 SQL Server 中使用什么底层机制来批量插入该数据?
SqlBulkCopy 的建议批量大小是多少?我正在寻找一个可以用作性能调整起点的通用公式。 最佳答案 我有一个导入实用程序与我的 SQL Server 实例位于同一物理服务器上。它使用自定义的 ID
这是 TABLE1 的架构: CREATE TABLE [dbo].[TABLE1] ( [id] [int] IDENTITY(1, 1) NOT NULL, [code] [int
要将数据从一个数据库复制到具有相同架构的不同服务器中的另一个数据库,我计划使用 C sharp 库中的 SqlBulkCopy 类。 SqlBulkCopy 在插入记录时是否会保持与数据表中相同的顺序
我可以忽略我传递给 SqlBulkCopy 的数据表中已存在于 sql 数据库中的数据的重复记录吗?如果是,那么如何,如果否和其他选项,还要解释我。 最佳答案 不,这不是内置的。您需要先清理客户端上的
我正在执行从 excel 电子表格到临时表的数据的 sql 批量复制,然后从临时表到生产数据库。 我的问题是,如果由于任何原因上传到临时表或生产数据库失败,事务是否回滚并且没有数据被导入或修改现有数据
我的软件可以部署在两种不同的配置中:一种是我全天偶尔收到单个数据点的涓流馈送,另一种是我在一天结束时得到所有数据的转储。对于日终转储,显然,我将使用具有可配置批处理大小的 SqlBulkCopy()
在我的网络应用程序中,用户可以一次插入大量数据,以提高性能,我正在使用 SqlBulkCopy 类。对于插入两个不同表的单个操作,它会运行多次。如果用户取消操作或操作失败,那么我需要回滚数据,因此我使
我有以下代码..它实际上使用 SQLBulkCopy 将数据插入目标。由于死锁,此代码在源 SQL 服务器中经常失败。仅供引用,正在复制的表可以在我们执行批量复制时使用(我的意思是一些插入/选择将运行
我正在尝试使用 SqlBulkCopy 通过在我的应用程序中手动填充 DataTable 来将新行插入到我的数据库表中。 这适用于所有表除了具有由 3 列组成的复合主键的表。每当我尝试将任何内容 Sq
我正在使用 SqlBulkCopy 将一批记录从 MySQL 复制到 SQL Server。 正好 30 秒后,我明白了 System.Data.SqlClient.SqlException (0x8
这是我的场景:我必须在表中导入大文件,所以我使用了 sqlBulkCopy,因为其他方法太慢了。 这是一个文件行的例子: String1|String2|String3|String4 这是表结构:
有人可以帮我解决这个错误吗?这是我的代码: using System; using System.Drawing; using System.Collections; using System.Com
我正在努力将数据库从 MS Access 迁移到 sql server。为了将数据移动到新表中,我决定编写一个同步例程,因为模式已经发生了相当大的变化,它让我可以在运行它的程序上运行测试,并在我需要新
我正在使用 SqlBulkCopy 对象将生成的几百万行插入到数据库中。唯一的问题是我要插入的表有一个标识列。我尝试将 SqlBulkCopyOptions 设置为 SqlBulkCopyOption
从 csv 文件插入数据。如何使用存储过程而不是 SqlBulkCopy 从数据表插入到数据库?当前使用: using (SqlBulkCopy sqlBulkCopy = new SqlBulkC
我正在尝试找到一种使用 SqlBulkCopy 向 MSSQLServer 表执行批量插入的方法,该方法将在出现错误时继续,并返回无法插入的任何行的数据表。 当我尝试使用 SqlBulkCopy 时,
我是一名优秀的程序员,十分优秀!