Как зайти в Даркнет?!
25th January, 01:11
4
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
893
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4380
0
Помогите пожалуйста решить задачи
24th November, 23:53
6084
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4395
0
Метода Крамера С++
23rd October, 11:55
4308
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Уменьшение количества повторяющихся кодов обработки ошибок в C#?
Я никогда не был полностью доволен тем, как работает обработка исключений, есть много исключений и try / catch приносит в таблицу (размотка стека и т. д.), но, похоже, в этом процессе нарушается большая часть модели OO.
В любом случае, вот в чем проблема:
Допустим, у вас есть какой-то класс, который обертывает или включает сетевые операции с файлом IO (например, чтение и запись в какой-то файл по какому-то конкретному пути UNC). По разным причинам вы не хотите, чтобы эти операции IO завершились неудачей, поэтому, если вы обнаружите, что они завершились неудачей, вы повторяете их и продолжаете повторять, пока они не завершатся успешно или вы не достигнете тайм-аута. У меня уже есть удобный класс RetryTimer, который я могу создать и использовать, чтобы перевести текущий поток в спящий режим между повторными попытками и определить, когда истек период ожидания и т. д.
Проблема в том, что у вас есть куча операций IO в нескольких методах этого класса, и вам нужно обернуть каждую из них в логику try-catch / retry.
Вот пример фрагмента кода:
RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
bool success = false;
while (!success)
{
try
{
// do some file IO which may succeed or fail
success = true;
}
catch (IOException e)
{
if (fileIORetryTimer.HasExceededRetryTimeout)
{
throw e;
}
fileIORetryTimer.SleepUntilNextRetry();
}
}
Итак, как избежать дублирования большей части этого кода для каждой операции file IO в классе? Мое решение состояло в использовании анонимных блоков делегатов и единственного метода в классе, который выполнял переданный ему блок делегатов. Это позволило мне делать подобные вещи другими методами:
this.RetryFileIO( delegate()
{
// some code block
} );
Мне это несколько нравится, но оставляет желать лучшего. Я бы хотел услышать, как другие люди решают подобные проблемы.
Это выглядит как отличная возможность взглянуть на аспектно-ориентированное программирование. Вот хорошая статья о AOP в .NET году . Общая идея заключается в том, что вы извлекли бы кросс-функциональную проблему (т. е. повторите попытку в течение x часов) в отдельный класс, а затем вы бы аннотировали любые методы, которые должны изменить свое поведение таким образом. Вот как это может выглядеть (с хорошим методом расширения на Int32)
[RetryFor( 10.Hours() )]
public void DeleteArchive()
{
//.. code to just delete the archive
}
Просто интересно, как вы считаете, что ваш метод оставляет желать лучшего? Вы можете заменить анонимный делегат на a.. по имени? делегат, что-то вроде
public delegate void IoOperation(params string[] parameters);
public void FileDeleteOperation(params string[] fileName)
{
File.Delete(fileName[0]);
}
public void FileCopyOperation(params string[] fileNames)
{
File.Copy(fileNames[0], fileNames[1]);
}
public void RetryFileIO(IoOperation operation, params string[] parameters)
{
RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
bool success = false;
while (!success)
{
try
{
operation(parameters);
success = true;
}
catch (IOException e)
{
if (fileIORetryTimer.HasExceededRetryTimeout)
{
throw;
}
fileIORetryTimer.SleepUntilNextRetry();
}
}
}
public void Foo()
{
this.RetryFileIO(FileDeleteOperation, "L:\file.to.delete" );
this.RetryFileIO(FileCopyOperation, "L:\file.to.copy.source", "L:\file.to.copy.destination" );
}
Вот что я недавно сделал. Это, вероятно, было сделано в другом месте лучше, но он кажется довольно чистым и многоразовым.
У меня есть служебный метод, который выглядит следующим образом:
public delegate void WorkMethod();
static public void DoAndRetry(WorkMethod wm, int maxRetries)
{
int curRetries = 0;
do
{
try
{
wm.Invoke();
return;
}
catch (Exception e)
{
curRetries++;
if (curRetries > maxRetries)
{
throw new Exception("Maximum retries reached", e);
}
}
} while (true);
}
Затем в моем приложении я использую синтаксис выражения c#'s Lamda, чтобы поддерживать порядок:
Utility.DoAndRetry( () => ie.GoTo(url), 5);
Это вызывает мой метод и повторяет попытку до 5 раз. При пятой попытке исходное исключение перестраивается внутри исключения повторной попытки.
Вы также можете использовать более OO подход:
- Создайте базовый класс, который выполняет обработку ошибок и вызывает абстрактный метод для выполнения конкретной работы. (Образец метода шаблона )
- Создайте конкретные классы для каждой операции.
Это имеет то преимущество, что вы называете каждый тип выполняемой операции и даете вам шаблон команды-операции были представлены как объекты.