Pull to refresh

Comments 39

как вариант: использовать потокобезопасный самописный менеджер памяти, поток которого не прервется? выделять и освобождать память через него, ну и следить через него за памятью которую «забыли» освободить.
это первое что в голову пришло, но может я что-то не допонял, давно не приходилось выделять память руками :)
Ммм… а зачем мне тогда .net, если к нему нужно писать менеджер памяти на неуправляемом языке? :)
Хороший вопрос, зачем вам .NET, если у вас много работы на низком уровне.

Пишите модули на С++ и подключайте их через COM, P/Invoke или просто используя C++/CLI. Я все проблемы взаимодействия с низкоуровневыми функциями решаю именно так.
У меня немного работы с неуправляемым кодом; так, исключительно Marshal.Alloc. Странно было бы из-за него писать целый менеджер. С COM там тоже песни, но это отдельно :)
Если использовать спецификации Automation — то никаких песен не будет.

А чем вам критические секции, CriticalFinalizerObject и SafeHandle не угодил? Поток нельзя прервать внутри критической секции, а последние два уничтожат заблудший указатель.
В гробу я видел и Automation, и ручной dereference. Спасибо, как говорится, проблевались :)

Если вы о Thread.BeginCriticalRegion, то абсолютно не вариант — поток можно прервать внутри такой критической секции, и он прервется. BeginCriticalRegion обещает только то, что в случае ошибки надо «выкинуть на мороз» весь AppDomain, т.к. продолжать может быть себе дороже.

Я же говорю, сложнее задача :)
Ну то, что описано в посте — это настолько редко встречающаяся совокупность условий, что я даже и не представляю, насколько велика вероятность такого события.

Я лично с таким никогда не встречался, и не знаю, существует ли проблема на самом деле.
Маловероятно != 0, к сожалению. Это как race condition: нету-нету, потом бах! — и все лежат :)
Ну, если вам Marshal выделяет память, а потом из-за ThreadAbort вы ее теряете, то тут есть момент, кто вызывает ThreadAbort?

Если система — то это скорее всего kill вашего приложения, либо выгрузка AppDomian. Опять же, AppDomian можете выгрузить и вы сами. Либо, вы можете сами прервать поток.

Соответственно, если система убивает ваше приложение — вы с этим ничего не сделаете, но очисткой памяти она займется сама. Если вы убиваете приложение, аппдомен или поток сами — вы можете завесить там все waithandle'ами, чтобы потоки умирали только в специально предназначенных для этого точках.

В общем случае, боюсь, задача решения не имеет.
Не обижайтесь, но ваш ответ из разряда "«считать количество ThreadAbortException». ThreadAbort — просто поток был прерван, далеко не факт, что это завершается приложение. Так что за вариант «скорее всего [это kill приложения]» меня бы уволили :)

Я нашел такое решение для общего случая, но
а) мне странно, что Рихтер об этом не написал
б) adontz ниже ругается на CER чего-то :)
Так я и не говорю, что любой ThreadAbort — это завершившееся приложение.
Юрка, и что же за решение?

П.С. ты чего такой дерзкий сегодня?:)
Млять, в пысы смайл забыл. Досылаю: :)
а в чем там жопа, расскажи:) я лох, хочу все знать.
Ну хоть ты не стебай :) Приду домой, расскажу. Подписывайся на rss статье и к камментам ;)
непонял — нафига выделение памяти вне try/catch блока? вставьте внутрь и забудьте
Ок, я вставлю его в try-catch. Прочтите условие еще раз. То, что я внесу его в try-catch, никак не спасет меня от ThreadAbortException
Маленький пример опровергает это:
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

Черт, не заметил что написал дважды.
Хм. Что именно вы опровергли?
то, что перенся allocation в try, даже в случае hread.abort…

ой, дошло. Память уже может быть выделена, а указатель не инициализаирован.

Прошу прощения, был неправ.
Можно ещё использовать наследники от CriticalFinalizerObject
SafeHandle — это да, но с ним задача неинтересна :)
Зато это самый правильный путь, который описан в Библии MSDN.
Она же (Библия) же пишет: «Дескриптор SafeHandle в некоторых контекстах не является подходящим» msdn.microsoft.com/ru-ru/library/ms228970.aspx. Давайте рассматривать ситуацию в этом контексте )
Разве в .NET нет сборщика мусора? Или он не помогает?
Marshall.AllocHGlobal выделяет неуправляемую память, про которую сборщик мусора не знает.
можно считать ThreadAbortException, и по достижение некотрого кретического их количества — перезагружать программу.
Вы, наверное, веб-программист?
Лучше сразу весь комп в ребут отправлять. )
UFO landed and left these words here
Поэкспериментировал с CER, результата нет. Странно, я думал CER для таких вещей…
CER как раз для таких вещей — собственно, и хотел вечеросм продемонстрировать все тонкости :) Там много неочевидного
Ага, давай. Будет интересно.
Помимо обёртки есть неплохой вариант никогда не использовать Thread.Abort
Ага. И тогда уже Domain.Unload тоже не использовать, да (тот тоже абортит все потоки)? Фикус в том, что ThreadAbortException — это асинхронное исключение; если вам это что-то говорит, конечно.
Only those users with full accounts are able to leave comments. Log in, please.