Я ищу хорошие идеи для реализации общего способа выполнения одной строки (или анонимного делегата) кода с тайм-аутом.
TemperamentalClass tc = new TemperamentalClass();
tc.DoSomething(); // normally runs in 30 sec. Want to error at 1 min
Я ищу решение, которое можно элегантно реализовать во многих местах, где мой код взаимодействует с темпераментным кодом (который я не могу изменить).
Кроме того, я хотел бы, чтобы код «тайм-аут», который нарушает работу, не мог выполняться дальше, если это возможно.
c#
multithreading
c#-3.0
asynchronous
timeout
chilltemp
источник
источник
Ответы:
Действительно сложная часть здесь заключалась в том, чтобы убить долгосрочную задачу, передав поток выполнения из действия обратно в место, где его можно было прервать. Я сделал это с помощью обернутого делегата, который пропускает поток для уничтожения в локальную переменную в методе, который создал лямбду.
Я представляю этот пример для вашего удовольствия. Метод, который вас действительно интересует - это CallWithTimeout. Это отменит долго работающий поток, прервав его и проглотив исключение ThreadAbortException :
Использование:
Статический метод, выполняющий работу:
источник
Мы используем такой код в производстве :
Реализация с открытым исходным кодом, эффективно работает даже в сценариях параллельных вычислений и доступна как часть общих библиотек Lokad
Этот код все еще глючит, вы можете попробовать с этой небольшой тестовой программой:
Есть состояние гонки. Вполне возможно, что ThreadAbortException вызывается после вызова метода
WaitFor<int>.Run()
. Я не нашел надежного способа исправить это, однако с помощью того же теста я не могу воспроизвести любую проблему с принятым ответом TheSoftwareJedi .источник
Ну, вы могли бы делать что-то с делегатами (BeginInvoke, с помощью обратного вызова, устанавливающего флаг - и исходного кода, ожидающего этот флаг или тайм-аут) - но проблема в том, что очень трудно закрыть работающий код. Например, убийство (или приостановка) потока опасно ... поэтому я не думаю, что есть простой способ сделать это надежно.
Я опубликую это, но заметьте, что это не идеально - это не останавливает долгосрочную задачу и не очищает должным образом при сбое.
источник
Некоторые незначительные изменения в великолепном ответе Поп-Каталина:
Добавлены перегрузки для поддержки работника сигнализации для отмены выполнения:
источник
Вот как я это сделаю:
источник
Я просто выбил это сейчас, так что это может потребовать некоторого улучшения, но будет делать то, что вы хотите. Это простое консольное приложение, но демонстрирует необходимые принципы.
источник
Как насчет использования Thread.Join (int timeout)?
источник