Обновление текстового поля во время выполнения другого потока WPF

#c# #wpf #thread-safety

#c# #wpf #безопасность потоков

Вопрос:

Вот архитектура моего приложения. У меня есть скрипт на Perl, который вызывается с помощью метода, приведенного ниже, при нажатии кнопки.

         ProcessStartInfo psStartInfo = new ProcessStartInfo("perl.exe");
        psStartInfo.Arguments = paramStr;
        psStartInfo.UseShellExecute = false;
        psStartInfo.RedirectStandardOutput = true;
        psStartInfo.RedirectStandardError = true;
        psStartInfo.CreateNoWindow = false;


        ps.StartInfo = psStartInfo;
        ps.Start();
        string os = ps.StandardOutput.ReadToEnd();
 

Приведенный выше код выполняется успешно. Существует текстовый файл, который создается с использованием скрипта Perl, который я запустил в вышеупомянутом коде. Я должен прочитать этот файл и показать все в нем в моем текстовом поле WPF. Этот файл Perl обновляется каждые 5-10 секунд. Я использую приведенный ниже код для чтения файла и отображения его в моем текстовом поле.

         dispatcherTimer = new DispatcherTimer();
        dispatcherTimer.Tick  = new EventHandler(dispatcherTimer_Tick);
        dispatcherTimer.Interval = new TimeSpan(0, 0, 30);
        dispatcherTimer.Start();

     private void dispatcherTimer_Tick(object sender, EventArgs e)
    {
        txtExecLog.Text = "";

        if (File.Exists("C:\FlashAuto\Execution_Logs\log.txt"))
        {
            File.Copy("C:\FlashAuto\Execution_Logs\log.txt", "C:\FlashAuto\Temp\log.txt", true);
            TextReader readLogs = new StreamReader("C:\FlashAuto\Temp\log.txt");
            string line = readLogs.ReadLine();
            while (line != null)
            {
                txtExecLog.Text  = "n"   line;
                line = readLogs.ReadLine();
                txtExecLog.ScrollToEnd();
            }

            CountLines = txtExecLog.LineCount - 1;
            readLogs.Close();
            // Forcing the CommandManager to raise the RequerySuggested event
            txtExecLog.ScrollToEnd();
            CommandManager.InvalidateRequerySuggested();
            readLogs.Dispose();
        }
        else
        {
            txtExecLog.Text  = "log file not found at: " DateTime.Now.ToString();
        }

    }
 

Вот в чем проблема:

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

Комментарии:

1. Каков размер сгенерированного файла? Это (загрузка файла в память, то же самое в текстовом поле), вероятно, приводит к увеличению потребления памяти.

2. Почему вы хотите скопировать исходный файл журнала во временный файл журнала, вы можете открыть исходный файл журнала только для чтения и обновить текстовое поле, прочитав только из исходного файла журнала? Возможно, вы также можете использовать компонент FileSystemWatcher для просмотра обновлений исходного файла журнала и продолжать обновлять текстовое поле…

3. Вы можете попробовать прочитать файл с File.ReadLines помощью (.NET 4), а затем заменить цикл while циклом foreach, чтобы добавить каждую строку в a StringBuilder .

4. Попробуйте включить TextReader readLogs = ... using(...) { } оператор into, чтобы гарантировать IDisposable.Dispose() , что будет вызван

5. Также — используйте текстовое поле. AppendText() вместо использования = в свойстве Text . Таким образом, вы не записываете всю строку в текстовое поле каждый раз. Вам также не понадобится функция ScrollToEnd() .