Реализовать jQuery-подобный document.ready-Event - PullRequest
0 голосов
/ 28 октября 2018

Я создаю основное приложение asp.net, которое использует новую функцию HostedService в ядре asp.net 2.1.Некоторые из этих служб, зарегистрированных через services.AddHostedService(), зависят от других служб, и я ищу способ уведомить «дочерние службы», когда «родительская служба» будет готова.

Моя первая реализация выгляделакак это:

// Parent class
public delegate void OnServiceReadyHandler(object sender);
public event OnServiceReadyHandler OnServiceReady;

public void Init()
{
    // Do stuff
    OnServiceReady?.Invoke(this);
}


// Child class
_parentService.OnServiceReady += (sender) =>
{
   // Do stuff
};

Но это приводит к проблеме, когда дочерний класс подписывается на OnServiceReady-Event после того, как он уже запущен, поэтому никогда не получает уведомление.

Затем я подумал о свойствев родительском классе что-то вроде IsRead, но это также может привести к условию гонки (между чтением свойства и подпиской на событие Ready).

В последнее время много работы в Интернете jQuerys document.ready - событие пришло мне в голову.Он срабатывает после того, как документ готов или сразу, если он уже находится в состоянии готовности.Я изменил свою реализацию следующим образом:

// Parent class
private bool IsReady { get; set; } = false;

public delegate void OnServiceReadyHandler(object sender);
private OnServiceReadyHandler onServiceReadyHandler;
public event OnServiceReadyHandler OnServiceReady
{
    add
    {
        if (!IsReady)
            onServiceReadyHandler = (OnServiceReadyHandler)Delegate.Combine(onServiceReadyHandler, value);
        else
            value(this); 
    }
    // Remove ...
}

public void Init()
{
    // Do stuff
    IsReady = true;
    OnServiceReady?.Invoke(this);
}


// Child class
_parentService.OnServiceReady += (sender) =>
{
   // Do stuff
};

Похоже, что все работает нормально, но мне интересно, есть ли а) все еще есть вероятность состояния гонки и клиент не получит уведомление здесь и б)более элегантное решение этой проблемы или эта реализация?

1 Ответ

0 голосов
/ 21 декабря 2018

Да, у вас все еще может быть состояние гонки:

if (!IsReady)
    onServiceReadyHandler = (OnServiceReadyHandler)Delegate.Combine(onServiceReadyHandler, value);

Может быть случай, когда IsReady оценивается как false, но перед обновлением обработчика событий, *Метод 1006 * устанавливает IsReady в true и запускает событие. Затем запускается вторая строка выше, и событие никогда не запускается снова.

Пример в документации по ключевому слову add показывает использование lock.Это, вероятно, то, что вы должны использовать здесь - в методах доступа add и remove, а также в вашем методе Init().

Кроме того, есть ли какая-то причина, по которой вы используете Delegate.Combine() здесь?Документы просто показывают, что вы можете использовать +=.

public event OnServiceReadyHandler OnServiceReady
{
    add
    {
        lock (onServiceReadyHandler) {
            if (!IsReady)
                onServiceReadyHandler += value;
            else
                value(this); 
        }
    }
    // Remove ...
}

public void Init()
{
    // Do stuff
    lock (onServiceReadyHandler) {
        IsReady = true;
    }
    OnServiceReady?.Invoke(this);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...