Комментарии 39
как вариант: использовать потокобезопасный самописный менеджер памяти, поток которого не прервется? выделять и освобождать память через него, ну и следить через него за памятью которую «забыли» освободить.
это первое что в голову пришло, но может я что-то не допонял, давно не приходилось выделять память руками :)
это первое что в голову пришло, но может я что-то не допонял, давно не приходилось выделять память руками :)
0
Ммм… а зачем мне тогда .net, если к нему нужно писать менеджер памяти на неуправляемом языке? :)
0
Хороший вопрос, зачем вам .NET, если у вас много работы на низком уровне.
Пишите модули на С++ и подключайте их через COM, P/Invoke или просто используя C++/CLI. Я все проблемы взаимодействия с низкоуровневыми функциями решаю именно так.
Пишите модули на С++ и подключайте их через COM, P/Invoke или просто используя C++/CLI. Я все проблемы взаимодействия с низкоуровневыми функциями решаю именно так.
0
У меня немного работы с неуправляемым кодом; так, исключительно Marshal.Alloc. Странно было бы из-за него писать целый менеджер. С COM там тоже песни, но это отдельно :)
0
Если использовать спецификации Automation — то никаких песен не будет.
А чем вам критические секции, CriticalFinalizerObject и SafeHandle не угодил? Поток нельзя прервать внутри критической секции, а последние два уничтожат заблудший указатель.
А чем вам критические секции, CriticalFinalizerObject и SafeHandle не угодил? Поток нельзя прервать внутри критической секции, а последние два уничтожат заблудший указатель.
0
В гробу я видел и Automation, и ручной dereference. Спасибо, как говорится, проблевались :)
Если вы о Thread.BeginCriticalRegion, то абсолютно не вариант — поток можно прервать внутри такой критической секции, и он прервется. BeginCriticalRegion обещает только то, что в случае ошибки надо «выкинуть на мороз» весь AppDomain, т.к. продолжать может быть себе дороже.
Я же говорю, сложнее задача :)
Если вы о Thread.BeginCriticalRegion, то абсолютно не вариант — поток можно прервать внутри такой критической секции, и он прервется. BeginCriticalRegion обещает только то, что в случае ошибки надо «выкинуть на мороз» весь AppDomain, т.к. продолжать может быть себе дороже.
Я же говорю, сложнее задача :)
+2
Ну то, что описано в посте — это настолько редко встречающаяся совокупность условий, что я даже и не представляю, насколько велика вероятность такого события.
Я лично с таким никогда не встречался, и не знаю, существует ли проблема на самом деле.
Я лично с таким никогда не встречался, и не знаю, существует ли проблема на самом деле.
0
Маловероятно != 0, к сожалению. Это как race condition: нету-нету, потом бах! — и все лежат :)
0
Ну, если вам Marshal выделяет память, а потом из-за ThreadAbort вы ее теряете, то тут есть момент, кто вызывает ThreadAbort?
Если система — то это скорее всего kill вашего приложения, либо выгрузка AppDomian. Опять же, AppDomian можете выгрузить и вы сами. Либо, вы можете сами прервать поток.
Соответственно, если система убивает ваше приложение — вы с этим ничего не сделаете, но очисткой памяти она займется сама. Если вы убиваете приложение, аппдомен или поток сами — вы можете завесить там все waithandle'ами, чтобы потоки умирали только в специально предназначенных для этого точках.
В общем случае, боюсь, задача решения не имеет.
Если система — то это скорее всего kill вашего приложения, либо выгрузка AppDomian. Опять же, AppDomian можете выгрузить и вы сами. Либо, вы можете сами прервать поток.
Соответственно, если система убивает ваше приложение — вы с этим ничего не сделаете, но очисткой памяти она займется сама. Если вы убиваете приложение, аппдомен или поток сами — вы можете завесить там все waithandle'ами, чтобы потоки умирали только в специально предназначенных для этого точках.
В общем случае, боюсь, задача решения не имеет.
0
Не обижайтесь, но ваш ответ из разряда "«считать количество ThreadAbortException». ThreadAbort — просто поток был прерван, далеко не факт, что это завершается приложение. Так что за вариант «скорее всего [это kill приложения]» меня бы уволили :)
Я нашел такое решение для общего случая, но
а) мне странно, что Рихтер об этом не написал
б) adontz ниже ругается на CER чего-то :)
Я нашел такое решение для общего случая, но
а) мне странно, что Рихтер об этом не написал
б) adontz ниже ругается на CER чего-то :)
0
а в чем там жопа, расскажи:) я лох, хочу все знать.
0
непонял — нафига выделение памяти вне try/catch блока? вставьте внутрь и забудьте
0
Ок, я вставлю его в try-catch. Прочтите условие еще раз. То, что я внесу его в try-catch, никак не спасет меня от ThreadAbortException
0
Маленький пример опровергает это:
В output
В output:
static void Main(string[] args) { Thread thr = new Thread(Start); thr.Start(); Thread.Sleep(100); thr.Abort(); Thread.Sleep(1000); } static void Start() { try { Console.WriteLine("Try"); Thread.Sleep(1000); } catch(Exception e) { Console.WriteLine(e.GetType()); } finally { Console.WriteLine("finally"); } }
В output
Try System.Threading.ThreadAbortException finally
В output:
try finally
0
Можно ещё использовать наследники от CriticalFinalizerObject
+3
SafeHandle — это да, но с ним задача неинтересна :)
-2
Зато это самый правильный путь, который описан в Библии MSDN.
0
Она же (Библия) же пишет: «Дескриптор SafeHandle в некоторых контекстах не является подходящим» msdn.microsoft.com/ru-ru/library/ms228970.aspx. Давайте рассматривать ситуацию в этом контексте )
0
Разве в .NET нет сборщика мусора? Или он не помогает?
0
можно считать ThreadAbortException, и по достижение некотрого кретического их количества — перезагружать программу.
0
НЛО прилетело и опубликовало эту надпись здесь
Поэкспериментировал с CER, результата нет. Странно, я думал CER для таких вещей…
0
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Интересная задачка: повышаем стабильность (robustness) приложений