Есть ли лучшая альтернатива попытке поймать безумие в приведенном ниже коде? Я собираю всевозможную подобную системную информацию, и у меня есть еще несколько этих надоедливых конструкций try catch, и я очень хотел бы избавиться от них.
Обратите внимание, что это действительно имеет смысл. Не вся информация о процессе в блоках try может быть получена, а то, что недоступно, в любом случае является необязательным, в то же время недопустимо пропускать то, что доступно, поэтому не существует только одной пары try catch.
Если бы только эти операторы try catch могли войти в метод Append().
foreach (Process proc in Process.GetProcesses())
{
try { Append(proc.Threads.Count); } catch { }
try { Append(proc.Id); } catch { }
try { Append(proc.ProcessName); } catch { }
try { Append(proc.BasePriority); } catch { }
try { Append(proc.StartTime); } catch { }
Append(proc.HandleCount,
proc.PrivateMemorySize64,
proc.NonpagedSystemMemorySize64,
proc.PagedMemorySize64,
proc.PeakPagedMemorySize64,
proc.PeakVirtualMemorySize64);
}
Однако сколько из этих строк может выйти из строя фактически? В моих тестах только StartTime мог привести к отказу в доступе. Другая информация представляется общедоступной независимо от того, есть ли у вас доступ к процессу или нет. (Предполагается, что Process — хорошо известный класс System.Diagnostics.Process.)
@ V0ldek Довольно сложно изменить встроенные в .NET классы или свойства, которые могут создавать ошибки.
Слово предупреждения, если это будет вызываться довольно часто и потенциально будет перехватывать множество исключений, это может стать серьезным ударом по производительности. Исключения довольно дороги, поэтому их следует избегать, если это вообще возможно.
@Denis Schaf - Почему это плохо?
Что заставляет вас думать, что если, например, proc.Id не удалось получить идентификатор процесса, вы могли бы получить имя процесса, базовый приоритет и т. д.? Другими словами: почему бы просто не использовать один try-catch для всех добавлений?
И, пожалуйста, ловите соответствующие исключения. Вы не хотите, чтобы NullReferenceException остался незамеченным.
@Jeroen Mostert - зависит от ОС. В моей программе их больше, и некоторые из них (информация о диске) не работают под Linux, но не под Windows.
@DavidG - вызывается только один раз за выполнение программы.
Вы не делаете ничего плохого, и ваш код безопасен, вы защищены, и эти функции могут вызывать исключения. Подход @MartinCostello выглядит элегантно, я бы проголосовал за это.
@elgonzo - я не знаю, и мне все равно, потому что я хочу надежный способ сделать это для всех случаев, которые мне нужны, и мне больше не нужно об этом думать. Возможно, это не очень хорошая идея.
Ну, вы могли бы просто использовать один try-catch, окружающий все ваши Appends. Что тогда было бы менее надежным?
elgonzo - Да, я это знаю (см. исходный вопрос), но я хочу убедиться, что ничего не пропущу.
Другой вариант — использовать директивы компилятора для выполнения только тех команд, которые, как вы знаете, будут работать на каждой платформе. См. здесь или здесь, как это сделать. Теперь вы просто обертываете все это одной попыткой/поймать.
@DavidG - И тогда мне нужно будет понять, что с чем работает. Гораздо проще, если у меня есть только один метод Append(), который всегда работает без сбоев.
@Martin Costello - кажется, ваши предложения работают, спасибо!
Да, лично я бы предпочел знать, что работает на каждой платформе...
@DavidG - это просто не вариант, потому что некоторые из этих перехватов попыток просто не работают в Linux, в то время как платформа поддерживает эти функции. Документация Microsoft, похоже, не содержит никакой информации об этом. Кроме того, существует проблема количества платформ и версий платформ. Огромная боль, которой можно полностью избежать одним методом благодаря Мартину Костелло.
Нет, версии платформы не будут иметь никакой разницы, он либо работает на платформе, либо нет. Ваш подход — это молоток для чего-то, что требует большей утонченности. Как вы видите в ответе Патрика, просто протестируйте каждую платформу, и если документы неверны/отсутствуют, обновите их — все они доступны для редактирования на Github.
@ DavidG - Но что я от этого получу, кроме дополнительного кода? Иногда чем проще, тем лучше.
Молча поедать исключения — это зло.
@ 3Dave - Не в этом случае. То, что недоступно, является необязательным. Информация, которую я собираю, хэшируется с помощью Sha256 для создания начального числа для некриптографического генератора случайных чисел, который не зависит от системного криптографического генератора случайных чисел. Таким образом, в этом случае информация, которую нельзя получить, действительно является необязательной, поэтому она не имеет значения. Это немного нишевый случай.





На мой взгляд, ваш подход в целом неверен, но он будет работать. Вы можете «оптимизировать» это в удобочитаемости, используя метод:
private void AppendSafe<T>(Func<T> f)
{
T val;
try
{
val = f();
}
catch { return; }
Append(val);
}
AppendSafe(() => proc.Threads.Count);
AppendSafe(() => proc.Id);
AppendSafe(() => proc.ProcessName);
AppendSafe(() => proc.BasePriority);
AppendSafe(() => proc.StartTime);
Но я бы сказал, чтобы поймать соответствующие исключения. Вы не хотите, чтобы NullReferenceException остался незамеченным.
Кроме того, поскольку исключения обходятся дорого, лучше выяснить, какие свойства доступны на каких платформах, и протестировать их. По крайней мере, вы минимизируете влияние на производительность при частом вызове этого.
Все исключения перехвачены в моем коде, я специально проверил каждое свойство на предмет этого. Код запускается только один раз за выполнение программы, так что это абсолютно не проблема.
В этом случае вы учитываете все журналы и т. д., Исключения первого шанса и т. д., Но в целом это хорошо.
Исключения могут быть проблемой в масштабе (может быть, экстремальный пример, но у Троя Ханта был свой проблемы с ними). Я думаю, что наша общая цель состоит в том, чтобы попытаться избежать их, если вы можете. Этот ответ отличный, но я бы предпочел понять для каждой платформы, что должно и не должно работать.
@DavidG Как я и предполагал («лучше выяснить, какие свойства доступны на каких платформах, и проверить это»).
Это нишевый случай. Информация собирается только для заполнения большого состояния некриптографического PRNG. Что доступно, а что нет на какой платформе, кажется не столь важным. Возможно, мне следовало уточнить это в исходном вопросе.
Вы можете добавить метод
SafeAppend<T>(Func<T> getter), который выполняетtry { Append(getter()); } catch { }, а затем использовать его в исходном коде:SafeAppend(() => proc.Threads.Count);