Я надеюсь, что вы будете терпеть меня. Я хотел предоставить как можно больше информации. Основная проблема заключается в том, как создать структуру (например, стек), которая будет использоваться несколькими потоками, которые будут извлекать значение и использовать его для обработки одного большого плоского файла и, возможно, выполнять цикл снова и снова, пока весь файл не будет обработан. Если файл содержит 100 000 записей, которые могут быть обработаны 5 потоками с использованием 2 000 фрагментов строк, то каждый поток получит для обработки 10 фрагментов.
Моя цель - переместить данные в плоский файл (с заголовком... Подзаголовок... Деталь, Деталь, Деталь,... Деталь, Поднижний колонтитул, Подзаголовок... Деталь, Деталь, Деталь,... Деталь, Поднижний колонтитул, Subheader...Detail, Detail, Detail, ...Detail, SubFooter, Footer) в базу данных OLTP с режимом восстановления до Simple (возможно, Full) в 3 таблицы: 1-я представляет уникальный ключ подзаголовка, присутствующий в строке подзаголовка, 2-я промежуточная таблица SubheaderGroup, представляющая группировку строк сведений в кусках по 2000 записей (должен иметь PK идентификатора подзаголовка в качестве его FK и 3-й, представляющий строки сведений с FK, указывающим на PK подзаголовка.
Я занимаюсь ручным управлением транзакциями, так как у меня могут быть десятки тысяч строк сведений, и я использую специальное поле, для которого установлено значение 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.
Итак, вопрос здесь заключается в том, что основная программа диктует, какая строка от строки до строки должна обрабатываться каждым потоком, и я думаю, что это должно происходить во время создания потока. Второе решение, вероятно, заключается в том, чтобы потоки разделяли некоторую структуру и использовали что-то уникальное для них (например, номер потока или порядковый номер) для поиска общей структуры (возможно, стека и извлечения значения (блокируя стек при этом), а затем следующий поток будет затем выберите следующее значение.Основная программа выберет плоский файл, определит размер фрагментов и создаст стек.
Итак, может ли кто-нибудь предоставить некоторые фрагменты кода, псевдокод того, как несколько потоков будут обрабатывать один файл и получать только уникальную часть этого файла?
Спасибо, Рэд