Научно-образовательный IT-форум

Объявление

Поддержать просветительскую деятельность форума можно по ссылке.
Публикация рекламы доступна через спонсорство канала YouTube.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Научно-образовательный IT-форум » Вопросы (задачи) » [+] Освобождение “ненужных” объектов при использовании LazyInitializer


[+] Освобождение “ненужных” объектов при использовании LazyInitializer

Сообщений 1 страница 2 из 2

1

LazyInitializer.EnsureInitialized<T>(T, Func<T>)

target T – ссылка для инициализации, если она еще не была инициализирована,
valueFactory Func<T> – функция, вызываемая для инициализации ссылки.

Этот метод может использоваться одновременно несколькими потоками для инициализации цели. В случае, если к этому методу одновременно обращаются несколько потоков, может быть создано несколько экземпляров T, но только один будет сохранен в target. В таком случае этот метод не будет удалять объекты, которые не были сохранены. Если такие объекты должны быть удалены, вызывающая сторона должна определить, не использовался ли объект, и затем удалить объект соответствующим образом.

Таким образом, если инициализатор создает объект, требующий освобождения, то ставший “ненужным” такой объект не сможет быть освобожден без написания дополнительной логики.

Реализуйте данную логику (в многопоточном сценарии) к данному примеру кода:

Код:
void Main()
{
    Expensive e = new Foo().Expensive;
}
class Foo
{
    Expensive _expensive;
    public Expensive Expensive
    {
        get
        {
            LazyInitializer.EnsureInitialized(ref _expensive, () =>
            {
                Expensive e = new Expensive();
                return e;
            });
            return _expensive;
        }
    }
}
class Expensive : IDisposable
{
    public Expensive()  { }
    public void Dispose()
    {
        Console.WriteLine("Object is disposed.");
    }
}

2

Предлагаю следующий способ решения задачи.

Код:
static ManualResetEvent _starter = new ManualResetEvent(false);
const int N = 4;
void Main()
{
    Foo f = new Foo();
    Thread[] T = new Thread[N];
    for (int i = 0; i < N; i++)
    {
        T[i] = new Thread(() => { Expensive e = f.Expensive; });
        T[i].Start();
    }
    for (int i = 0; i < N; i++)
        T[i].Join();
    _starter.Set();
    Thread.Sleep(1000); // some work
}
class Foo
{
    Expensive _expensive;
    public Expensive Expensive
    {
        get
        {
            LazyInitializer.EnsureInitialized(ref _expensive, () =>
            {
                Expensive e = new Expensive();
                var tokenReady = new ManualResetEventSlim();
                RegisteredWaitHandle reg = null;
                reg = ThreadPool.RegisterWaitForSingleObject
                (_starter,
                (data, timeOut) =>
                {
                    tokenReady.Wait();
                    tokenReady.Dispose();
                    if (e != _expensive) e.Dispose();
                    else e.NotDispose();
                    reg.Unregister(_starter);
                },
                null, -1, true);
                tokenReady.Set();
                return e;
            });
            return _expensive;
        }
    }
}
class Expensive : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine($"Object with hash code {this.GetHashCode().ToString()} is disposed.");
    }
    public void NotDispose()
    {
        Console.WriteLine($"Object with hash code {this.GetHashCode().ToString()} not disposed.");
    }
}

Быстрый ответ

Напишите ваше сообщение и нажмите «Отправить»



Вы здесь » Научно-образовательный IT-форум » Вопросы (задачи) » [+] Освобождение “ненужных” объектов при использовании LazyInitializer