Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
213 / 139 / 8
Регистрация: 18.08.2010
Сообщений: 1,018

Использовать один блок try{} вместо двух, сохраняя производительность

26.09.2012, 11:38. Показов 1347. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
LeniumSoft, а как бы вы переработали вот этот метод? Как видите, тут я кучу блоков try{} тоже наставил... Сделал я это по той причине, чтобы при каждом сохранении скрина не проверять существование папки (лишние операции с файловой системой ведь очень дорогостоящие по ресурсам). А если папка не существует, то возникнет исключение, и только уже после этого мы проверим, существует ли папка. И если нет, тогда создаем ее и пробуем вторую попытку создания скрина.
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
        private void SaveScreen(Bitmap bitmap, string fileName, string datePath, EncoderParameters encParams)
        {
            while (true) //При нормальной работе без исключений этот цикл проходит только один раз
            {
                try
                {
                    bitmap.Save(fileName, jgpEncoder, encParams);
                    break; //Сохранение скрина прошло успешно. Выходим из цикла
                }
                catch (Exception ex)
                {
                    if (!Directory.Exists(datePath))//если исключение возникло по той причине, что не существовало папки для скринов
                    {
                        try
                        {
                            //тогда пробуем ее создать
                            Directory.CreateDirectory(datePath);
                        }
                        catch (Exception exep)
                        {
                            //не получилось создать папку, потому записываем в лог сообщение об ошибке и выходим из цикла так и не сохранив скрин...
                            Debugging.LogError(exep, "Folder for screens can't created: " + datePath);
                            break;
                        }
                    }
                    else
                    {
                        //произошла неизвестная ошибка сохранения скрина, потому записываем в лог сообщение об ошибке и выходим из цикла так и не сохранив скрин...
                        Debugging.LogError(ex, "Error saving screen in file " + fileName);
                        break;
                    }
                }
            }
            // метод SaveScreen() не вызывается, когда bitmap == null, потому в данном месте я проверку на null во второй раз опустил
            //еще.. Я не вызывал Dispose() в блоке finally выше по той причине, так как цикл while выполнится по второму кругу, если не существовало папки для кринов, чтобы сохранить скрин в только что созданную папку
            bitmap.Dispose();
        }
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.09.2012, 11:38
Ответы с готовыми решениями:

Jugged (ступенчатые) массивы: Вместо двух циклов for использовать один foreach
Приветствую. В одном из курсов по программированию на C# есть тема про ступенчатые массивы. В качестве дополнительного задания к уроку...

Как использовать один запрос вместо двух?
В CMS есть различные типы внутренних объектов. У каждого объекта есть основные поля, общие для всех объектов (таблица objects). И...

Связанный список - использовать в функции один указатель вместо двух
Возможно ли использовать в этой функции один указатель вместо двух (*cur и *prev) ? #include <stdio.h> #include...

9
 Аватар для LeniumSoft
1454 / 847 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
26.09.2012, 12:22
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
private void SaveScreen(Bitmap bitmap, string fileName, string datePath, EncoderParameters encParams)
        {
            try
            {
                if (bitmap == null || String.IsNullOrEmpty(fileName) || String.IsNullOrEmpty(datePath) || encParams == null) return;
 
                DirectoryInfo directoryInfo = new DirectoryInfo(datePath);
                if (!directoryInfo.Exists)
                    directoryInfo.Create();
 
                bitmap.Save(fileName, jgpEncoder, encParams);
            }
            catch (IOException ex)
            {
                //Не удалось создать директорию.
            }
            catch (Exception ex)
            {
                //Все остальные ошибки.
            }
            finally
            {
                if (bitmap != null)
                    bitmap.Dispose();
            }
        }
Добавлено через 16 минут
Цитата Сообщение от Tolias28 Посмотреть сообщение
Сделал я это по той причине, чтобы при каждом сохранении скрина не проверять существование папки (лишние операции с файловой системой ведь очень дорогостоящие по ресурсам)
Тебе лучше сделать некий класс который будет держать переменную типа DirectoryInfo и который будет создавать папку и знать есть она на диске или нет! Вот тогда будет самый минимальный расход ресурсов!

Вечером если смогу, то опишу механизм подробнее!
1
213 / 139 / 8
Регистрация: 18.08.2010
Сообщений: 1,018
26.09.2012, 20:03  [ТС]
Вы сделали то, чего я как раз и избегал - ваш код проверяет существование директории каждый при создании скрина!
0
 Аватар для LeniumSoft
1454 / 847 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
26.09.2012, 20:58
Цитата Сообщение от LeniumSoft Посмотреть сообщение
Тебе лучше сделать некий класс который будет держать переменную типа DirectoryInfo и который будет создавать папку и знать есть она на диске или нет! Вот тогда будет самый минимальный расход ресурсов!
Вечером если смогу, то опишу механизм подробнее!
Вот это отменяется! Ввиду того что я разобраля в работе свойства Exists.

Цитата Сообщение от Tolias28 Посмотреть сообщение
Вы сделали то, чего я как раз и избегал - ваш код проверяет существование директории каждый при создании скрина!
Теперь надо тебе рассказать что же происходит!

И так! Само свойство:
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
/// <summary>
    /// Получает значение, определяющее наличие каталога.
    /// </summary>
    /// 
    /// <returns>
    /// Значение true, если каталог существует; в противном случае — значение false.
    /// </returns>
    /// <filterpriority>1</filterpriority>
    public override bool Exists
    {
      [SecuritySafeCritical] get
      {
        try
        {
          if (this._dataInitialised == -1)
            this.Refresh();
          if (this._dataInitialised != 0)
            return false;
          else
            return this._data.fileAttributes != -1 && (this._data.fileAttributes & 16) != 0;
        }
        catch
        {
          return false;
        }
      }
    }
Если переменная _dataInitialized равна -1 вызывается метод Refresh.

Как же он работает:
C#
1
2
3
4
5
6
7
8
9
/// <summary>
    /// Обновляет состояние объекта.
    /// </summary>
    /// <exception cref="T:System.IO.IOException">Устройство, например дисковод, не готово. </exception><filterpriority>1</filterpriority>
    [SecuritySafeCritical]
    public void Refresh()
    {
      this._dataInitialised = File.FillAttributeInfo(this.FullPath, ref this._data, false, false);
    }
Присваивает нашей переменной значение выданное функцией FillAttributeInfo

Она довольно большая и выполняет много работы!

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
[SecurityCritical]
    internal static int FillAttributeInfo(string path, ref Win32Native.WIN32_FILE_ATTRIBUTE_DATA data, bool tryagain, bool returnErrorOnNotFound)
    {
      int num = 0;
      if (tryagain)
      {
        Win32Native.WIN32_FIND_DATA wiN32FindData = new Win32Native.WIN32_FIND_DATA();
        string fileName = path.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
        int newMode = Win32Native.SetErrorMode(1);
        try
        {
          bool flag = false;
          SafeFindHandle firstFile = Win32Native.FindFirstFile(fileName, wiN32FindData);
          try
          {
            if (firstFile.IsInvalid)
            {
              flag = true;
              num = Marshal.GetLastWin32Error();
              switch (num)
              {
                case 2:
                case 3:
                case 21:
                  if (!returnErrorOnNotFound)
                  {
                    num = 0;
                    data.fileAttributes = -1;
                    break;
                  }
                  else
                    break;
              }
              return num;
            }
          }
          finally
          {
            try
            {
              firstFile.Close();
            }
            catch
            {
              if (!flag)
                __Error.WinIOError();
            }
          }
        }
        finally
        {
          Win32Native.SetErrorMode(newMode);
        }
        data.PopulateFrom(wiN32FindData);
      }
      else
      {
        bool flag = false;
        int newMode = Win32Native.SetErrorMode(1);
        try
        {
          flag = Win32Native.GetFileAttributesEx(path, 0, ref data);
        }
        finally
        {
          Win32Native.SetErrorMode(newMode);
        }
        if (!flag)
        {
          num = Marshal.GetLastWin32Error();
          switch (num)
          {
            case 2:
            case 3:
            case 21:
              if (!returnErrorOnNotFound)
              {
                num = 0;
                data.fileAttributes = -1;
                break;
              }
              else
                break;
            default:
              return File.FillAttributeInfo(path, ref data, true, returnErrorOnNotFound);
          }
        }
      }
      return num;
    }
Но вернёмся к Exists.

Из него видно что он вызовет всё это чудо только первый раз. При следующих обращениях он нам просто будет выдавать то что получил первый раз. Соответственно тебе надо только DirectoryInfo вывести за метод и не инициализировать постоянно! Тоесть один раз его создал указав путь к папке и потом в своём методе проверяй свойство Exists.
1
213 / 139 / 8
Регистрация: 18.08.2010
Сообщений: 1,018
26.09.2012, 22:48  [ТС]
LeniumSoft, спасибо за такой довольно развернутый исследовательский ответ

Не по теме:

Вы не против, если мы продолжим обсуждение по коду в личке или в другой теме на форуме? То, о чем мы сейчас уже начали обсуждать, никому из людей, использующих HideScreener, не особо нужно и интересно:)

0
 Аватар для LeniumSoft
1454 / 847 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
26.09.2012, 23:07
Цитата Сообщение от Tolias28 Посмотреть сообщение
Вы не против, если мы продолжим обсуждение по коду в личке или в другой теме на форуме? То, о чем мы сейчас уже начали обсуждать, никому из людей, использующих HideScreener, не особо нужно и интересно

Не по теме:

:) Я не против!

0
213 / 139 / 8
Регистрация: 18.08.2010
Сообщений: 1,018
26.09.2012, 23:31  [ТС]
Вынес обсуждение из этой темы. Думаю, модераторы не будут против)
Продолжу...

Согласно поданной вами информации посмотрим теперь на производительность моего первоначального метода и сравним его с вашим методом, предложенным в вот этом посте. Я первоначально использовал вот такой метод:
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
        private void SaveScreen(Bitmap bitmap, string fileName, string datePath, EncoderParameters encParams)
        {
            while (true) //При нормальной работе без исключений этот цикл проходит только один раз
            {
                try
                {
                    bitmap.Save(fileName, jgpEncoder, encParams);
                    break; //Сохранение скрина прошло успешно. Выходим из цикла
                }
                catch (Exception ex)
                {
                    if (!Directory.Exists(datePath))//если исключение возникло по той причине, что не существовало папки для скринов
                    {
                        try
                        {
                            //тогда пробуем ее создать
                            Directory.CreateDirectory(datePath);
                        }
                        catch (Exception exep)
                        {
                            //не получилось создать папку, потому записываем в лог сообщение об ошибке и выходим из цикла так и не сохранив скрин...
                            Debugging.LogError(exep, "Folder for screens can't created: " + datePath);
                            break;
                        }
                    }
                    else
                    {
                        //произошла неизвестная ошибка сохранения скрина, потому записываем в лог сообщение об ошибке и выходим из цикла так и не сохранив скрин...
                        Debugging.LogError(ex, "Error saving screen in file " + fileName);
                        break;
                    }
                }
            }
            // метод SaveScreen() не вызывается, когда bitmap == null, потому в данном месте я проверку на null во второй раз опустил
            //еще.. Я не вызывал Dispose() в блоке finally выше по той причине, так как цикл while выполнится по второму кругу, если не существовало папки для кринов, чтобы сохранить скрин в только что созданную папку
            bitmap.Dispose();
        }
Вы мне предложили сделать вот так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void SaveScreen(Bitmap bitmap, string fileName, string datePath, EncoderParameters encParams)
        {
            try
            {
                if (DirectoryInfo.Exists)
                    directoryInfo.Create();
 
                bitmap.Save(fileName, jgpEncoder, encParams);
            }
            catch (IOException ex)
            {
                //Не удалось создать директорию.
            }
            catch (Exception ex)
            {
                //Все остальные ошибки.
            }
            finally
            {
                if (bitmap != null)
                    bitmap.Dispose();
            }
        }
Согласно той информации, которую вы навели о свойстве DirectoryInfo.Exists, вынесем код этого свойства прямо в вами предложенный метод, чтобы визуально можно было сравнить количество операций при вашем методе и при моем:
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
        private void SaveScreen2(Bitmap bitmap, string fileName, string datePath, EncoderParameters encParams)
        {
            try
            {
                //вынесем свойство DirectoryInfo.Exists прямо сюда, сэмулировав его:
                bool PropertyExists;
                try
                {
                    if (this._dataInitialised == -1)
                        this.Refresh();
                    if (this._dataInitialised != 0)
                        PropertyExists = false;
                    else
                        PropertyExists = this._data.fileAttributes != -1 && (this._data.fileAttributes & 16) != 0;
                }
                catch
                {
                    PropertyExists = false;
                }
                //конец сэмулированного свойства DirectoryInfo.Exists
 
                if (PropertyExists)
                    directoryInfo.Create();
 
                bitmap.Save(fileName, jgpEncoder, encParams);
            }
            catch (IOException ex)
            {
                //Не удалось создать директорию.
            }
            catch (Exception ex)
            {
                //Все остальные ошибки.
            }
            finally
            {
                if (bitmap != null)
                    bitmap.Dispose();
            }
        }
И что мы видим? два блока try - один в другом. Вау! А мы то начинали разговор о том, как избежать вложенных блоков, вспоминаете? А результат то получился таким самым. Даже более, ваш метод получился не такой оптимальный как мой. В моем методе в 95% случаев работает только один блок try, так как в 95% случаев папка для скринов существует. И потому мой метод в 95% случаев исполняет только вот эти две строчки:
C#
1
2
3
4
5
6
7
8
9
try
                {
                    bitmap.Save(fileName, jgpEncoder, encParams);
                    break; //Сохранение скрина прошло успешно. Выходим из цикла
                }
                catch (Exception ex)
                {
                ......
                }
А вами предложенный метод кроме того, что исполняет строчку bitmap.Save(), также исполняет вот это:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//вынесем свойство DirectoryInfo.Exists прямо сюда, сэмулировав его:
                bool PropertyExists;
                try
                {
                    if (this._dataInitialised == -1)
                        this.Refresh();
                    if (this._dataInitialised != 0)
                        PropertyExists = false;
                    else
                        PropertyExists = this._data.fileAttributes != -1 && (this._data.fileAttributes & 16) != 0;
                }
                catch
                {
                    PropertyExists = false;
                }
                //конец сэмулированного свойства DirectoryInfo.Exists
 
                if (PropertyExists)
К тому же получились вложенные блоки try (в моем методе вложенные блоки только в catch, а они там вызываются очень редко). Мой итог: ваш совет не дал возможности уменьшить колиство влоежнных блоков try, к тому же в производительности ваш метод тоже проигрывает. Покажите, в чем я не прав
0
 Аватар для LeniumSoft
1454 / 847 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
27.09.2012, 11:59
Ёлки палки! Про try catch мы говорили когда ты строку в bool парсил! Насчёт этого метода ты попросил показать как бы я его переписал! Я тебе его переписал более понятно и красиво! Без бесполезных зацикливаний и прочего! Причём тут вообще try catch? Этот код работает с файловой системой и его надо засунуть в try от греха! Я не пойму за какой производительностью ты гонишься? Эти оба метода отработают очень быстро и ты этого даже не заметишь! Сохрани в начале метода колличество текущих тиков и в конце метода отними от текущих тиков то значение которое ты получил вначале.

C#
1
2
3
4
5
long ticksCount = Environment.TickCount;
 
...
 
int milliseconds = TimeSpan.FromTicks(Environment.TickCount - ticksCount).Milliseconds;
В переменной milliseconds ты увидишь колличество милисекунд за которые отработал твой метод! И скорее всего это будет ноль или единица если сохраняемая картинка много весит!

Я то тебе представил более понятный и не запутанный метод! А работает он так же!
0
213 / 139 / 8
Регистрация: 18.08.2010
Сообщений: 1,018
27.09.2012, 13:29  [ТС]
Вы меня неправильно поняли, а я вас... В результате получилось черт знает что Извините... Тогда проехали....

Добавлено через 25 минут
Я бываю иногда очень озабочен граммами производительности, даже если код от этого становится не такой красив.. но это наверное плохо?
0
 Аватар для LeniumSoft
1454 / 847 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
27.09.2012, 20:18
Цитата Сообщение от Tolias28 Посмотреть сообщение
Я бываю иногда очень озабочен граммами производительности, даже если код от этого становится не такой красив.. но это наверное плохо?
Надо просто использовать это там где надо! Вот когда тебе надо будет сохранять по 500 картинок в секунду стоит заботится о каждом такте! А когда сохраняется картинка в 10 секунд можно и пограмотнее для себя писать! Ну а когда для других пишешь так надо вообще идеально!
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.09.2012, 20:18
Помогаю со студенческими работами здесь

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

Сделать вместо двух бордеров один
&lt;input placeholder=&quot;Логин&quot; name = 'login' type=&quot;text&quot; pattern=&quot;{2,64}&quot; required title=&quot;Разрешены только буквы на английской и русской...

Функция выводит один результат вместо двух
здравствуйте. функция должна выводить 2 переменных, но по факту выводит только одну ( первую прописанную в квадратные скобки ) скажите...

Заменить один элемент строки вместо двух
Здравствуйте уважаемые форумчане. Столкнулся с такой проблемой: Есть строка:ssssssdfhsdhdffhghgfhfghhhjj, с помощью кривых манипуляций...

Как использовать один Enum в двух проектах по связной ссылке?
Такая ситуация есть два проекта в одном решении, первый собирается в DLL, второй в EXE, в одном и в другом проекте нужно использовать...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! в-строка - входное арифметическое выражение в инфиксной(обычной). . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru