[Минутка хардкора-10]: Смертельная гонка
Сбж, он же
Be Careful Where You Put GC.SuppressFinalize от Alois Craus.
Он же "Как не надо использовать финалайзеры, сложный способ"
P.S. И да пребудет с вами SafeHandle.
P.P.S. Чтобы два раза не вставать: Matt Warren,
Resources for Learning about .NET Internals . На удивление полный список.
Re: [Минутка хардкора-10]: Смертельная гонка
Здравствуйте, Sinix, Вы писали:
S>Сбж, он же Be Careful Where You Put GC.SuppressFinalize от Alois Craus.
S>Он же "Как не надо использовать финалайзеры, сложный способ"
public class Event : IDisposable
{
internal IntPtr hGlobal; // allocate some unmanaged memory
public Event()
{
hGlobal = Marshal.AllocHGlobal(500);
}
~Event() // finalizer
{
Dispose();
}
public void Dispose()
{
if ( hGlobal != IntPtr.Zero) // check if memory is gone
{
Marshal.FreeHGlobal(hGlobal); // free it
GC.SuppressFinalize(this ); // Prevent finalizer from running it again
hGlobal = IntPtr.Zero;
}
}
}
Вызывать из финализатора GC.SuppressFinalize(this) это явный косяк товарища.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[2]: [Минутка хардкора-10]: Смертельная гонка
От:
Sinix
Дата: 15.02.18 10:46
Оценка:
Здравствуйте, romangr, Вы писали:
R>Вызывать из финализатора GC.SuppressFinalize(this) это явный косяк товарища.
Как бы да, но там не в этом дело, см секцию "Is This A Problem?"
Re: [Минутка хардкора-10]: Смертельная гонка
Здравствуйте, Sinix, Вы писали:
S>Он же "Как не надо использовать финалайзеры, сложный способ"
А надо ли их вообще использовать? Я всегда освобождаю явно, если есть какие-то неуправляемые ресурсы.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[2]: [Минутка хардкора-10]: Смертельная гонка
От:
Sinix
Дата: 17.02.18 11:02
Оценка:
Здравствуйте, CoderMonkey, Вы писали:
S>>Он же "Как не надо использовать финалайзеры, сложный способ"
CM>А надо ли их вообще использовать? Я всегда освобождаю явно, если есть какие-то неуправляемые ресурсы.
За исключением довольно редких случаев — не надо. Проще SafeHandle прикрутить, по ссылке в конце есть UPD с примером.
Явное освобождение — не панацея, до первого исключения доживёт. Неприятно, особенно если ресурс разделяемый.
Re[3]: [Минутка хардкора-10]: Смертельная гонка
Здравствуйте, Sinix, Вы писали:
S>Явное освобождение — не панацея, до первого исключения доживёт.
В смысле? Dispose / using
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[4]: [Минутка хардкора-10]: Смертельная гонка
Здравствуйте, CoderMonkey, Вы писали:
CM>В смысле? Dispose / using
Контрпример: асинхронное исключение строго после отработки конструктора. Объект сразу отправляется в мусор, Dispose в finally блоке не вызывается.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[5]: [Минутка хардкора-10]: Смертельная гонка
Здравствуйте, hardcase, Вы писали:
H>асинхронное исключение строго после отработки конструктора.
А можно пример?
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[6]: [Минутка хардкора-10]: Смертельная гонка
Здравствуйте, CoderMonkey, Вы писали:
CM>А можно пример?
Complications with ThreadAbort
Например, рассмотрим код:
using (StreamWriter w = File.CreateText ("myfile.txt" ))
{
w.Write ("Abort-Safe?" );
}
Конструкция using — это синтаксический сахар, разворачивается примерно в следующее:
StreamWriter w;
w = File.CreateText ("myfile.txt" );
try
{
w.Write ("Abort-Safe" );
}
finally
{
w.Dispose();
}
ThreadAbortException может выскочить после создания StreamWriter, но перед заходом в блок try.
В MSIL это видно:
IL_0001: ldstr "myfile.txt"
IL_0006: call class [mscorlib]System.IO.StreamWriter
[mscorlib]System.IO.File::CreateText(string )
IL_000b: stloc.0
.try
{
...
Поэтому может так случиться, что блок finally вызван не будет и файловый хендл будет закрыт только
когда GC соберет мусор и дело дойдет до вызова финализатора SafeHandle.
Защититься от ThreadAbortException можно, например, поместив код в блок finally:
try
{
}
finally
{
using (StreamWriter w = File.CreateText ("myfile.txt" ))
{
w.Write ("Abort-Safe?" );
}
}
Или использовать
Constrained Execution Regions ... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[7]: [Минутка хардкора-10]: Смертельная гонка
Здравствуйте, romangr, Вы писали:
R>Защититься от ThreadAbortException можно, например, поместив код в блок finally:
Лучший способ защититься от ThreadAbortException — не использовать Thread.Abort()
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[8]: [Минутка хардкора-10]: Смертельная гонка
Здравствуйте, CoderMonkey, Вы писали:
CM>Лучший способ защититься от ThreadAbortException — не использовать Thread.Abort()
Начинание неплохое, но прочих мероприятий не отменяет
В FW таки есть способы нечаянно вызвать Abort, как пример — выгрузка доменов или вызов Response.End() (возможно, непрямой. Скажем, через Response.Redirect() и Server.Transfer()).
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить