Я надеюсь, что вы будете терпеть меня. Я хотел предоставить как можно больше информации.
Основная проблема заключается в том, как создать структуру (например, стек), которая будет использоваться несколькими потоками, которые будут извлекать значение и использовать его для обработки одного большого плоского файла и, возможно, повторять циклы снова и снова, пока не будет обработан весь файл.
Если файл содержит 100 000 записей, которые могут быть обработаны 5 потоками, используя 2000 строк
тогда каждый поток получит 10 блоков для обработки.
Моя цель - переместить данные в плоский файл (с заголовком ... Subheader ... Detail, Detail, Detail, ... Detail, SubFooter, Subheader ... Detail, Detail, Detail, ... Detail SubFooter,
Subheader ... Detail, Detail, Detail, ... Detail, SubFooter, структура нижнего колонтитула) в БД OLTP, которая имеет режим восстановления в Простое (возможно полное) в 3 таблицы: первая представляет уникальный ключ подзаголовка, присутствующий в строке подзаголовка, вторая - промежуточное Таблица SubheaderGroup, представляющая группировку строк подробностей в порциях из 2000 записей (должна иметь идентификатор PK подзаголовка в качестве своего FK и 3-я, представляющая строки подробностей с FK, указывающим на PK подзаголовка.
Я занимаюсь ручным управлением транзакциями, поскольку могу иметь десятки тысяч строк Detail.
и я использую специальное поле, которое установлено в 0 в таблицах назначения во время загрузки, а затем в конце обработки файла я выполняю обновление транзакций, меняя это значение на 1, что может сигнализировать другому приложению, что загрузка завершена.
Я хочу нарезать этот плоский файл на несколько равных частей (одинаковое количество строк), которые можно обработать несколькими потоками и импортировать с помощью SqlBulkCopy с использованием IDataReader, созданного из метаданных таблицы назначения).
Я хочу использовать шаблон производителя / потребителя (как описано в ссылке ниже - анализ PDF и пример кода) для использования SqlBulkCopy с опцией SqlBulkCopyOptions.TableLock.
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);
}
}
Этот метод будет выполнен в контексте нового потока. Я хочу, чтобы этот новый поток читал только уникальный фрагмент исходного плоского файла, а другой поток будет непосредственно обрабатывать следующий фрагмент. Затем потребители будут перемещать данные (которые передаются им) в базу данных SQL Server с использованием класса SqlBulkCopy ADO.NET.
Таким образом, вопрос заключается в том, чтобы основная программа диктовала, какой lineFrom к lineTo должен обрабатываться каждым потоком, и я думаю, что это должно происходить при создании потока.
Второе решение, вероятно, состоит в том, чтобы потоки разделяли некоторую структуру и использовали что-то уникальное для них (например, номер потока или порядковый номер) для поиска общей структуры (возможно, стека и извлечения значения (блокировки стека при этом)), а затем следующий поток будет затем выберите следующее значение. Основная программа выберет плоский файл и определит размер фрагментов и создаст стек.
Так может ли кто-нибудь предоставить фрагменты кода, псевдокод о том, как несколько потоков будут обрабатывать один файл и получать только уникальную часть этого файла?
Спасибо,
Rad