Как читать большие текстовые файлы в C #? - PullRequest
0 голосов
/ 07 июля 2019

У меня есть выигрышная форма, и я хочу прочитать текстовый файл и показать его в списке, но возникает проблема, когда я пытаюсь загрузить файл размером 1-3 МБ через несколько секунд, после чего выдается это исключение:

Помощник по управляемой отладке 'ContextSwitchDeadlock': 'CLR не удалось перейти из контекста COM 0x149cf10 в контекст COM 0x149ce58 в течение 60 секунд.Поток, которому принадлежит целевой контекст / квартира, скорее всего, либо делает ожидание без перекачки, либо обрабатывает очень длительную операцию без перекачки сообщений Windows.Эта ситуация, как правило, оказывает негативное влияние на производительность и может даже привести к тому, что приложение перестает отвечать на запросы или использование памяти постоянно увеличивается с течением времени.Чтобы избежать этой проблемы, все потоки однопотоковых квартир (STA) должны использовать примитивы перекачки (такие как CoWaitForMultipleHandles) и регулярно перекачивать сообщения во время длительных операций. '

и вот мой код:

private void Button7_Click(object sender, EventArgs e)
    {
        openFileDialog = new OpenFileDialog();
        if (openFileDialog.ShowDialog() == DialogResult.OK)
        {
            StreamReader sr = new StreamReader(openFileDialog.FileName);
            var emails = sr.ReadToEnd();
            foreach (var items in emails)
            {
                aFlistBoxEmail.Items.Add(items);
            }
        }
    }

также я использую это решение, но это не помогло: введите описание ссылки здесь

Ответы [ 5 ]

1 голос
/ 07 июля 2019

Вы можете попробовать прочитать все строки сразу:

private async void Button7_Click(object sender, EventArgs e)
{
    openFileDialog = new OpenFileDialog();
    if (openFileDialog.ShowDialog() == DialogResult.OK)
        aFlistBoxEmail.DataSource = File.ReadAllLines(openFileDialog.FileName);
}
0 голосов
/ 07 июля 2019

это не обязательно означает, что у вас есть проблема, но это может вызвать проблемы, так как вы работаете в основном потоке пользовательского интерфейса - так что ваше приложение будет зависать, пока читатель не закончит свою работу, и так как это тяжелый файл, вы получаю эту ошибку. Вы можете отключить это в:

Отладка> windows> Настройки исключений> Помощники по управляемой отладке (развернуть)> отключить "ContextSwitchDeadlock"

это хорошая идея поместить эту задачу в поток или задачу и убедиться, что вы попытались поймать INSIDE метод также на случай, если он не удастся (или оператор using) а между тем (до тех пор, пока программа чтения файлов не завершит работу) вы можете отобразить в пользовательском интерфейсе сообщение «приложение занято» или что-то подобное.

Thread thread = new Thread(Butoon_Click(sender, ev));
thread.IsBackground = true;
0 голосов
/ 07 июля 2019

Когда есть длительный процесс, приложение автоматически переходит в режим без ответа, поскольку длительный процесс находится внутри потока пользовательского интерфейса. Лучше использовать асинхронное программирование с использованием await & async, это поможет запуститьдлительные действия в отдельном потоке, и это не нарушит поток пользовательского интерфейса.Мой пример кода приведен ниже.

private async void Button7_Click(object sender, EventArgs e)
{
    openFileDialog = new OpenFileDialog();
    if (openFileDialog.ShowDialog() == DialogResult.OK)
    {
        StreamReader sr = new StreamReader(openFileDialog.FileName);
        var emails =  await sr.ReadToEndAsync();
        foreach (var items in emails)
        {
            aFlistBoxEmail.Items.Add(items);
        }
    }
}

Часть для чтения файлов можно переместить в другую функцию, чтобы она могла дать больше модуляции.

0 голосов
/ 07 июля 2019

Почему вы делаете это точно? Ваш код добавляет каждый отдельный символ в текстовом файле как отдельную запись в поле списка, с 3 МБ файлом будет много записей, не нужно ли сначала анализировать текст по определенному значению или классу? если вы пытаетесь читать электронные письма из файла, разбейте файл, например, таким образом, например string.Split('\n');, таким образом, вы разделяете каждое письмо, а затем анализируете их, используя класс MailAddress из System.Net.Mail.MailAddress

0 голосов
/ 07 июля 2019

Ваш обработчик кликов выполняется в потоке пользовательского интерфейса, который также запускает насос сообщений для вашего приложения. Поскольку ваш обработчик занимает так много времени, он делает ваше приложение не реагирующим на пользовательский интерфейс и системные события в течение периода, который, вероятно, недопустим.

Вы можете решить проблему, сделав свою логику асинхронной.

private async Task Button7_Click(object sender, EventArgs e)
{
    openFileDialog = new OpenFileDialog();
    if (openFileDialog.ShowDialog() == DialogResult.OK)
    {
        StreamReader sr = new StreamReader(openFileDialog.FileName);
        var emails = await sr.ReadToEndAsync();
        foreach (var items in emails)
        {
            aFlistBoxEmail.Items.Add(items);
        }
    }
}
...