sankarisiva Ответов: 1

Проблемы взаимоблокировки при преобразовании основной массы записей из DBF в CSV


Привет, я пытаюсь преобразовать visual box из DBF-файла в CSV-файл с помощью приложения visual studio 2008 c# windows. Я успешно подключаюсь к visual foxpro и читаю файл.Я использовал oledbdataadapter для заполнения набора данных, я потерпел неудачу здесь с проблемой взаимоблокировки, потому что я работаю около 800000+ записей. Поэтому я иду с oledbdatareader, читаю каждую строку и записываю в csv-файл. Он работает нормально, но после написания 400000+ записей я снова столкнулся с тупиковой проблемой. Мне нужно записать все 800000 + записей в один CSV-файл. Я приложил сюда свой код. Пожалуйста, помогите записать 800000 + записей в один CSV-файл .

OleDbCommand oleDbCommand = new OleDbCommand(query, oleDbConnection);
oleDbCommand.CommandTimeout = 60000;
using (OleDbDataReader oleDbDataReader = oleDbCommand.ExecuteReader())
{
    using (streamWriter1)
    {
        int fieldCount = oleDbDataReader.FieldCount;
        string columns = string.Empty;
        StringBuilder fullFile = new StringBuilder();
        for (int i = 0; i < fieldCount; i++)
        {
            columns += oleDbDataReader.GetName(i);
            if (i != fieldCount - 1)
            {
                columns += ",";
            }
        }
        fullFile.Append(columns);
        fullFile.Append("\r\n");
        streamWriter1.Write(fullFile.ToString());
        int j = 0;
        while (oleDbDataReader.Read())
        {
            j++;
            string rows = string.Empty;
            for (int i = 0; i < fieldCount; i++)
            {
                rows += oleDbDataReader.GetValue(i).ToString().Trim();
                rows += i != fieldCount - 1 ? "," : "";
            }
            fullFile = new StringBuilder();
            fullFile.Append(rows);
            fullFile.Append("\r\n");
            streamWriter1.Write(fullFile.ToString());
        }
    }
    oleDbDataReader.Close();
    oleDbCommand.Dispose();
    oleDbConnection.Close();  
}


Что я уже пробовал:

Я попытался записать каждые 200000 записей в другой файл. Но эта логика также потерпела неудачу с тупиковыми проблемами после записи 400000 записей.

Richard MacCutchan

Что вы подразумеваете под"тупиком"? Что же происходит на самом деле?

sankarisiva

Я получаю сообщение об ошибке типа «CLR не удалось перейти из COM-контекста 0x50aea88 в COM-контекст 0x50aebf8 в течение 60 секунд. Поток, которому принадлежит целевой контекст / квартира, скорее всего, либо выполняет ожидание без перекачки, либо обрабатывает очень долгое время. работа без перекачки сообщений Windows. Эта ситуация обычно отрицательно сказывается на производительности и может даже привести к тому, что приложение перестает отвечать или использование памяти постоянно накапливается с течением времени. Чтобы избежать этой проблемы, все потоки однопоточного подразделения (STA) должны использовать примитивы ожидания перекачки (например, CoWaitForMultipleHandles) и регулярно перекачивают сообщения во время длительных операций ".

Richard MacCutchan

Сколько записей вы пытаетесь прочитать в вашем OleDbDataReader за один раз?

sankarisiva

Всего 800000 + записей. Зацикливая oleDbDataReader, я читаю одну запись за раз и записываю эту запись в CSV-файл.

Richard MacCutchan

Это слишком много, вам нужно разбить его на управляемые куски по несколько сотен за раз.

sankarisiva

У меня есть один файл DBF. можете ли вы помочь разбить этот файл на небольшие куски или написать запрос на чтение нескольких сотен строк за раз? Мой текущий запрос - " Select * from instable. dbf"

1 Ответов

Рейтинг:
6

Jochen Arndt

Я не знаю, является ли это причиной, но вы не должны создавать новый StringBuilder объект внутри цикла while, использующий имя уже существующего объекта (я не уверен, что повторное использование имени объекта таким образом создает утечку памяти).:

while (oleDbDataReader.Read())
{
    // ...
    // Avoid this:
    //fullFile = new StringBuilder();
    // Use this instead:
    fullFile.Clear();
    fullFile.Append(rows);
    fullFile.Append("\r\n");
    streamWriter1.Write(fullFile.ToString());
}

Если это не источник ошибок, то он должен, по крайней мере, улучшить производительность.
По той же причине вы также можете изменить генерацию rows строка.

[РЕДАКТИРОВАТЬ]
Из комментариев следует, что выполнение этой задачи в рабочем потоке может решить проблему. При выполнении таких длительных задач в потоке графического интерфейса он не сможет отвечать на сообщения во время выполнения задачи.

Некоторые ссылки о рабочих потоках:
Класс BackgroundWorker (System.ComponentModel)[^]
Пример класса BackgroundWorker для начинающих[^]
[/РЕДАКТИРОВАТЬ]


sankarisiva

Спасибо за ваш ответ. Но это решение не улучшает процесс... я получаю тот же результат, что и до этого изменения

Jochen Arndt

Тем временем я прочитал ваши вышеприведенные комментарии.

Вы делаете это в своем собственном потоке?
Если нет, то вам следует создать рабочий поток.

sankarisiva

ох. С помощью рабочего потока мы можем решить эту проблему? Можете ли вы привести какой-нибудь пример или ссылку

Jochen Arndt

Если это работает в вашем графическом потоке, он будет блокировать графический интерфейс до тех пор, пока не вернется.
Из Вашего сообщения об ошибке:
"очень длительная работа без перекачки сообщений Windows"
Использование рабочего потока-это обычный вариант (лучше, чем перекачка сообщения, как указано в сообщении об ошибке).

Кончик:
Следуйте моим предложениям по оптимизации. Если затем вы записали больше записей, чем раньше, то использование рабочего потока должно быть решением.

sankarisiva

Спасибо. Я не работал с рабочим потоком в прошлом. Итак, теперь я изучаю ключевой момент использования рабочего потока и опубликую свой комментарий после получения наилучшего результата. Спасибо еще раз

Jochen Arndt

Я обновил свое решение, включив в него две ссылки о рабочих потоках.

sankarisiva

Спасибо...

sankarisiva

Большое вам спасибо, Йохен. Теперь все работает нормально. Результаты очень точны.

Jochen Arndt

Приятно слышать, что проблема решена, и благодарить вас за то, что вы приняли это решение.