[Минутка хардкора-10]: Смертельная гонка
От: Sinix  
Дата: 15.02.18 07:05
Оценка: 23 (3)
Сбж, он же Be Careful Where You Put GC.SuppressFinalize от Alois Craus.
Он же "Как не надо использовать финалайзеры, сложный способ"

P.S. И да пребудет с вами SafeHandle.

P.P.S. Чтобы два раза не вставать: Matt Warren, Resources for Learning about .NET Internals. На удивление полный список.
Отредактировано 15.02.2018 7:14 Sinix . Предыдущая версия .
минутка хардкора
Re: [Минутка хардкора-10]: Смертельная гонка
От: romangr Россия  
Дата: 15.02.18 08:05
Оценка: 3 (1) +1
Здравствуйте, 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]: Смертельная гонка
От: CoderMonkey  
Дата: 17.02.18 05:35
Оценка:
Здравствуйте, 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]: Смертельная гонка
От: CoderMonkey  
Дата: 17.02.18 17:53
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Явное освобождение — не панацея, до первого исключения доживёт.


В смысле? Dispose / using
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[4]: [Минутка хардкора-10]: Смертельная гонка
От: hardcase Пират http://nemerle.org
Дата: 17.02.18 18:39
Оценка: +1
Здравствуйте, CoderMonkey, Вы писали:

CM>В смысле? Dispose / using


Контрпример: асинхронное исключение строго после отработки конструктора. Объект сразу отправляется в мусор, Dispose в finally блоке не вызывается.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[5]: [Минутка хардкора-10]: Смертельная гонка
От: CoderMonkey  
Дата: 17.02.18 20:27
Оценка:
Здравствуйте, hardcase, Вы писали:

H>асинхронное исключение строго после отработки конструктора.


А можно пример?
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[6]: [Минутка хардкора-10]: Смертельная гонка
От: romangr Россия  
Дата: 18.02.18 13:08
Оценка: 25 (3) +1
Здравствуйте, 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]: Смертельная гонка
От: CoderMonkey  
Дата: 18.02.18 18:51
Оценка:
Здравствуйте, romangr, Вы писали:

R>Защититься от ThreadAbortException можно, например, поместив код в блок finally:


Лучший способ защититься от ThreadAbortException — не использовать Thread.Abort()
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[8]: [Минутка хардкора-10]: Смертельная гонка
От: Sinix  
Дата: 19.02.18 06:46
Оценка: 8 (1)
Здравствуйте, CoderMonkey, Вы писали:


CM>Лучший способ защититься от ThreadAbortException — не использовать Thread.Abort()


Начинание неплохое, но прочих мероприятий не отменяет В FW таки есть способы нечаянно вызвать Abort, как пример — выгрузка доменов или вызов Response.End() (возможно, непрямой. Скажем, через Response.Redirect() и Server.Transfer()).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.