C # Оптимальный способ хранить и выводить список строк - PullRequest
0 голосов
/ 30 января 2019

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

WPF:

<TextBox Text="{Binding StatusMessage}" TextWrapping="Wrap" AcceptsReturn="True" />

Метод 1:

private void OutputMessage(string msg)
{
    //Result
    //1000  Lines     108ms
    //10000 Lines    1687ms
    if(!string.IsNullOrEmpty(msg))
    {
        string msgWithTimeStamp = System.DateTime.Now.ToString() + ": \t" + msg;

        int msgLine = 0;
        if (!string.IsNullOrEmpty(StatusMessage))
        {
            //Only show 500 lines of latest messages...
            msgLine = StatusMessage.Count(m => m == '\n');
            if (msgLine > 500)
                StatusMessage = StatusMessage.Remove(0, StatusMessage.IndexOf("\n") + 1);

            StatusMessage = StatusMessage + "\n" + msgWithTimeStamp;
        }
        else
            StatusMessage = msgWithTimeStamp;
    }
}

Метод 2 (Лучшая производительность):

List<string> msgList;
private void OutputMessage(string msg)
{
    //Result
    //1000  Lines     31ms
    //10000 Lines    377ms
    if (!string.IsNullOrEmpty(msg))
    {
        string msgWithTimeStamp = System.DateTime.Now.ToString() + ": \t" + msg;
        msgList.Add(msgWithTimeStamp);

        if (msgList.Count > 500)
            msgList.RemoveAt(0);

        StatusMessage = String.Join("\n", msgList);
    }
}

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Вместо использования TextBox вы можете использовать ItemsControl, а данные связывают его ItemsSource с ObservableCollection.Затем вы просто добавляете каждое новое сообщение в ObservableCollection, и ItemsControl автоматически обновляется, чтобы показать новую запись в конце своего списка.

0 голосов
/ 30 января 2019

Самая большая проблема заключается в следующей строке:

StatusMessage = String.Join("\n", msgList);

Это означает, что вы перестраиваете всю строку каждый раз, когда обновляется основной список строк, и она проходит по всему списку, выделяя новые буферы памяти добуфер достаточно большой, чтобы заполнить всю строку (все 500 строк).Когда ваш список сообщений увеличивается до 500 строк, это означает, что следующее сообщение приведет к выделению 500 буферов просто для восстановления полной строки.

Лучшим способом было бы сохранить StringBuilder рядом с вашим списком сообщений (вваша msgList переменная).StringBuilder умен в том, как он распределяет буферы при изменении ваших сообщений.

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

// Somewhere in your code, probably next to your [msgList] variable...
private StringBuilder sb = new StringBuilder();

private void OutputMessage(string msg)
{
    if (!string.IsNullOrEmpty(msg))
    {
        string msgWithTimeStamp = System.DateTime.Now.ToString() + ": \t" + msg;
        msgList.Add(msgWithTimeStamp);
        sb.AppendLine(msgWithTimeStamp);

        if (msgList.Count > 500)
        {
            sb.Remove(0, msgList[0].Length + 2); // The +2 is to account for the new line and carriage return characters.
            msgList.RemoveAt(0);
        }

        statusMessage = sb.ToString();
    }
}

Единственным недостатком этого подхода является поддержание одного и того же набора сообщений дважды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...