Hello. Tell me how best to implement the display of the log on the screen? The log is displayed as text in real time while the program is running.

I tried the usual RichText, but after 2-3 lines of text it starts to blunt terribly. Lines are added to the end and the cursor moves to the last line. And processing 40 thousand records from the database (2-3 records in the log for 1 record from the database) takes 6-7 hours. Without output to the screen - processing takes 58 minutes.

  • one
    RichTextBox is really not adapted for working with large texts. But are you sure that with such a volume of log entries you really need this log? There will not find anything, at least without a search. Perhaps it makes sense to log everything to a file, and to display only critical entries in the UI (errors, for example). - andreycha
  • Well, if you want to stay with your, then show the code. Strings are immutable, and working with them can eat a lot of memory, for example, thereby slowing down work. - andreycha
  • In the file and so logged. In general, yes, I thought about it. To display only the necessary records. - Atlantis
  • one
    I think this way in any case you need to go. UI is needed for the user. And the user does not need hundreds of thousands of lines, he needs important brief information: errors, the number of processed records, etc. - andreycha

3 answers 3

System.Windows.Forms.ListView + ListView.VirtualMode allows you to work with large amounts of data for display.

    A large number of records can be quickly output to the DataGridView.
    Below is an example in which 500 thousand lines are output and a new record is added to the log every 50 ms.

    enter image description here


    // Microsoft (R) Roslyn C# Compiler version 1.1.0.51204 #r "System.Windows.Forms" using System.Windows.Forms; static DataGridView LogView(int columns) { var g = new DataGridView() { Dock = DockStyle.Fill, RowHeadersVisible = false, ColumnHeadersVisible = false, AutoGenerateColumns = false, AllowUserToAddRows = false, AllowUserToDeleteRows = false, GridColor = System.Drawing.Color.WhiteSmoke, AllowUserToResizeRows = false, VirtualMode = true }; for (var i=0; i < columns; i++) g.Columns.Add("c" + i, ""); g.Columns[columns-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; return g; } 

     class LogRow { public int RowId; public object Data; } var logui = LogView(2); // по-запросу возвращаем значения, необходимые для вывода в ui logui.CellValueNeeded += (s, e) => { var row = log[e.RowIndex]; switch(e.ColumnIndex) { case 0: e.Value = row.RowId; break; case 1: e.Value = row.Data; break; } }; var f = new Form() { Width = 800, Height = 300 }; f.Controls.Add(logui); // загружаем 500 тыс. записей var log = Enumerable .Range(0, 500000) .Select(i => new LogRow { RowId = i, Data = DateTime.Now.Ticks }) .ToList(); logui.RowCount = log.Count; // добавляем новую запись каждый 50 ms new Timer() { Interval = 50, Enabled = true }.Tick += delegate { log.Add(new LogRow { RowId = logui.RowCount, Data = DateTime.Now.Ticks }); logui.RowCount++; f.Text = "LOG: " + logui.RowCount; }; f.ShowDialog(); 

    To compile the code and run the application, for example, in Visual Studio Community 2015, you need to open View - Other Windows - C# Interactive , copy the code into it and press Enter .

    Visual Studio Community 2015 is a free version, you can download it here .

      If RichText slows down, then you can try TextBox (Multiline = true).

      I know from experience that an extra output even on the console slows down the processing.

      In order to give the user adequate information, and not a bunch of running text, it is better to report on the process of processing in%, the number of records processed correctly and with error records, etc. ... At the same time, it makes sense to update the interface not for each processed record, but for example, every 1 second.

      To optimize the performance of your algorithm, I can offer:

      • Work in multiple threads. Each stream can read from the database, process and write the results.
      • Logs better to write to the file. And do it in batches of N lines without a general blocking of threads.
      • Use SqlBulkCopy for multiple inserts into the database, if possible.