Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
1 / 1 / 0
Регистрация: 03.02.2012
Сообщений: 22
1

Как можно оптимизировать код?

10.07.2013, 12:41. Показов 894. Ответов 9
Метки нет (Все метки)

Здравствуйте, помогите пожалуйста ускорить работу программы.

Программа читает журнал событий винды, и выводит в gridControl.
На форме есть кнопка, при нажатии на которую создается элемент этого класса, а потом вызывается метод FilterAndShowEvents.
Этот класс отвечает за чтение и вывод журнала.

ListOfEvents - открывает журнал с указанным именем и переносит записи в список Log.
FilterAndShowEvents - удаляет записи с дублирующимися сообщениями, и заносит в gridControl.

Выполняется очень долго, подскажите что можно исправить.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
 
 
namespace events
{
 
    class ListOfEvents
    {
        //Класс список событий
        //Конструктор открывает файл, и считывая строки создает записи типа EventLog, которые помещает в список
        //Метод FilterOfEvents отфильтровывает список, делая из множества записей об одном событии одну запись
        //Метод ShowInGridView запускает метод FilterOfEvents, чтобы неотфильтрованные записи не попали в gridView, переводит записи в тип Record, и указывает список из записей типа Record как DataSource GridControl'a
        public List<EventLogItem> Log;
 
        public ListOfEvents(string LogName, string MachineName, DevExpress.XtraEditors.ProgressBarControl progressbar1)
        {
            EventLog ev = new EventLog(LogName, MachineName);
            Log = new List<EventLogItem>();
            if (ev.Entries.Count > 0)
            {
                for (int i = 0; i < ev.Entries.Count; i++)
                {
                    Log.Add(new EventLogItem(ev.Entries[i]));
                    progressbar1.Position += 1;
                    progressbar1.Update();
                }
            }
            ev.Close();
        }
 
        public void FilterAndShowEvents(DevExpress.XtraGrid.Views.Grid.GridView gridView1, DevExpress.XtraGrid.GridControl gridControl1, DevExpress.XtraEditors.ProgressBarControl progressbar1)
        {
            gridView1.Columns.Clear();
            BindingList<EventRecord> listDataSource = new BindingList<EventRecord>();
 
            List<string> messages = new List<string>();//список сообщений
            for (int i = 0; i < Log.Count; i++)
            {
                messages.Add(Log[i].Message);
                progressbar1.Position += 1;
                progressbar1.Update();
            }
            messages = messages.Distinct().ToList();//список сообщений без  повторений
 
            //выбор групп с одинаковым сообщением, и помещение 1 элемента из каждой группы в отфильтрованный список
            for (int i = 0; i < messages.Count; i++)
            {
                List<EventLogItem> EventsWithCurrentMessage = Log.FindAll(
    delegate(EventLogItem el)
    {
        return el.Message == messages[i];
    }
    );  //лист всех событий с текущим сообщением
 
                EventLogItem elem = EventsWithCurrentMessage[0];
                if (elem != null)
                {
                    listDataSource.Add(new EventRecord(elem.MachineName,elem.DateTime,elem.Message,elem.Action));
                }
 
                Log.RemoveAll(
delegate(EventLogItem el)
{
    return el.Message == messages[i];
}
); // удалить из списка все события с уже отработанным сообщением
                progressbar1.Position += EventsWithCurrentMessage.Count;
                progressbar1.Update();
        }
 
            gridControl1.DataSource = listDataSource;
            //настройка ширины столбцов
            gridView1.Columns[0].Width = gridView1.CalcColumnBestWidth(gridView1.Columns[0]);
            gridView1.Columns[1].Width = gridView1.CalcColumnBestWidth(gridView1.Columns[1]);
            gridView1.Columns[2].Width = (gridView1.CalcColumnBestWidth(gridView1.Columns[2])) / 5;
            gridView1.Columns[3].Width = gridView1.CalcColumnBestWidth(gridView1.Columns[3]);
 
        }
 
    }
}

Для хранения единичной записи используется класс EventLogItem, а для занесения в таблицу EventRecord, но там нет ничего нагромажденного как здесь, так нечего улучшать, так что проблема в этом классе.

Добавлено через 2 часа 35 минут
Немного изменил метод FilterAndShowEvents , работает на 30 секунд быстрее, но все равно долго. Нынешняя версия выглядит так:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
     public void FilterAndShowEvents(DevExpress.XtraGrid.Views.Grid.GridView gridView1, DevExpress.XtraGrid.GridControl gridControl1, DevExpress.XtraEditors.ProgressBarControl progressbar1)
        {
            gridView1.Columns.Clear();
            BindingList<EventRecord> listDataSource = new BindingList<EventRecord>();
 
            //выбор групп с одинаковым сообщением, и помещение 1 элемента из каждой группы в отфильтрованный список
            for (int i = 0; i < Log.Count; i++)
            {
                List<EventLogItem> EventsWithCurrentMessage = Log.FindAll(
    delegate(EventLogItem el)
    {
        return el.Message == Log[i].Message;
    }
    );  //лист всех событий с текущим сообщением
 
                EventLogItem elem = EventsWithCurrentMessage[0];
                if (elem != null)
                {
                    listDataSource.Add(new EventRecord(elem.MachineName,elem.DateTime,elem.Message,elem.Action));
                }
 
                Log.RemoveAll(
delegate(EventLogItem el)
{
    return el.Message == Log[i].Message;
}
); // удалить из списка все события с уже отработанным сообщением
                i = 0;
                progressbar1.Position += EventsWithCurrentMessage.Count;
                progressbar1.Update();
        }
 
            gridControl1.DataSource = listDataSource;
            //настройка ширины столбцов
            gridView1.Columns[0].Width = gridView1.CalcColumnBestWidth(gridView1.Columns[0]);
            gridView1.Columns[1].Width = gridView1.CalcColumnBestWidth(gridView1.Columns[1]);
            gridView1.Columns[2].Width = (gridView1.CalcColumnBestWidth(gridView1.Columns[2])) / 5;
            gridView1.Columns[3].Width = gridView1.CalcColumnBestWidth(gridView1.Columns[3]);
 
        }
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.07.2013, 12:41
Ответы с готовыми решениями:

Подскажите, как можно оптимизировать код?
Код проверяет, что нет такого ид в переменной for (int i = 0; c33 &lt;...

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

Насколько можно оптимизировать этот программный код?
static void Main(string args) { int massiv1 = new int; Random...

Как оптимизировать код?
Всем добрый день) Недавно начал изучать C# и решил написать такую программу: В 50-х годах XX века...

9
Master of Orion
Эксперт .NET
6085 / 4941 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
10.07.2013, 13:56 2
Запустить профайлер, он подскажет, какой конкретно метод исправлять, только он и нужен нам)
1
1 / 1 / 0
Регистрация: 03.02.2012
Сообщений: 22
10.07.2013, 14:46  [ТС] 3
Спасибо за совет, но я уже в программу встроил таймер чтобы смотреть что да как.
Убрал все, что можно было безболезненно убрать, работает гораздо быстрее, осталось убрать/заменить один кусок кода и все.
Подскажите чем менее затратным можно заменить вот эту часть?
C#
1
2
3
4
5
6
Log.RemoveAll(
delegate(EventLogItem el)
{
    return ((el.Message == Log[i].Message)&&(el.DateTime==Log[i].DateTime));
}
);;
она находится в цикле, и поэтому вызывается много раз. Там суть в том, что из всех событий с определенным сообщением и временем нужно добавить только одно, все остальные удалить.

Я подумал, что гораздо лучше будет удалить дубликаты из списка до цикла методом Distinct(), но он работает для просто списков, а не для списка классов. Вы не знаете, можно ли как-нибудь применить его к такому списку?
0
Master of Orion
Эксперт .NET
6085 / 4941 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
10.07.2013, 14:57 4
ObiomoFF, логику словами опишите.

А профайлер с таймером сравнивать все равно, что полноценный дебаггер с отладочной печатью
0
52 / 45 / 4
Регистрация: 07.10.2010
Сообщений: 95
10.07.2013, 15:10 5
C#
1
public List<EventLogItem> Log;
переделать на какой то
C#
1
Dictionary<string, List<EventLogItem>> a
Log.FindAll Log.RemoveAll переделать на работу с ключем Dictionary.
0
1 / 1 / 0
Регистрация: 03.02.2012
Сообщений: 22
11.07.2013, 07:18  [ТС] 6
Сделал свой Comparer для класса, как написано вот здесь http://msdn.microsoft.com/en-u... s.90).aspx, стало гораздо быстрее работать.

Но работа с прогрессбаром занимает очень много времени.
У меня в метод передается прогресс бар, и там в циклах увеличиваю позицию на 1.Может его можно как-нибудь оптимальнее выполнить?
0
Эксперт .NET
15321 / 11613 / 3047
Регистрация: 17.09.2011
Сообщений: 19,439
11.07.2013, 11:31 7
Цитата Сообщение от ObiomoFF Посмотреть сообщение
Но работа с прогрессбаром занимает очень много времени.
У меня в метод передается прогресс бар, и там в циклах увеличиваю позицию на 1.Может его можно как-нибудь оптимальнее выполнить?
Обновляйте прогресс не каждую итерацию, а каждые 10, например.
Еще лучше, заведите 2 переменных и один таймер с интервалом 100мс: в переменных храните общее количество записей и обработанное количество. А по тику таймера высчитывайте из этих переменных прогресс и обновляйте интерфейс (10 раз в секунду — более чем достаточно для оконного приложения).
1
1 / 1 / 0
Регистрация: 03.02.2012
Сообщений: 22
11.07.2013, 12:14  [ТС] 8
kolorotur, спасибо за совет, сделал обновление каждый сотый раз, работает гораздо быстрее.
0
Master of Orion
Эксперт .NET
6085 / 4941 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
11.07.2013, 13:58 9
ObiomoFF, сделайте обновление не каждый сотый раз, а каждые 100мс, ускорите еще намного )
0
141 / 180 / 44
Регистрация: 25.04.2012
Сообщений: 2,623
Записей в блоге: 5
11.07.2013, 17:35 10
Можно попробовать создать
C#
1
List<Thread>
и в него отправлять все запуски этого
C#
1
2
3
4
5
6
 Log.RemoveAll(
delegate(EventLogItem el)
{
    return el.Message == Log[i].Message;
}
);
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.07.2013, 17:35

Как оптимизировать код?
Подскажите пожалуйста, как в данном коде избавиться от необходимости каждый раз перед...

Подскажите как оптимизировать код
Собственно вот... void CalcValue(dynamic e) { var rez = e.GetType(); ...

Как оптимизировать код ввода из консоли?
Простите, возможна как-нибудь оптимизировать?

Можно ли, и если можно то как перевести код SQL в код С#
КОД ПРОГРАММЫ void __fastcall TForm1::SKChange(TObject *Sender) //Выбор таблицы { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.