实现类似jQuery的document.ready-Event

时间:2018-10-28 13:26:24

标签: c# events asp.net-core

我正在创建一个asp.net核心应用程序,该应用程序使用了asp.net core 2.1的新HostedService功能。通过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,但这也可能导致争用情况(在读取属性和预订就绪事件之间)。

最近想到jQuerys document.ready-event做很多网络工作。在文档准备就绪后立即触发,或者如果文档已经处于就绪状态则立即触发。我将实现更改为:

// 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
};

这看起来工作正常,但我想知道是否还有a)出现竞争状况的机会,而客户未在此处得到通知,b)对于此问题或此实现的更优雅的解决方案?

1 个答案:

答案 0 :(得分:1)

是的,您仍然可以在这里保持比赛条件:

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

您可能遇到将IsReady评估为false的情况,但是在可以更新事件处理程序之前,Init()方法将IsReady设置为{{1}并触发该事件。 然后上面的第二行运行,该事件再也不会触发。

example in the documentation for the add keyword显示lock的用法。这可能是您应该在这里使用的-在trueadd访问器中,以及您的remove方法中。

此外,您在这里使用Init()的原因是什么?文档只是显示您可以使用Delegate.Combine()

+=