实现类似document.ready-Event的jQuery



我正在创建一个asp.net核心应用程序,该应用程序使用asp.net核心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事件已经激发之后订阅它时,这会导致一个问题,因此永远不会得到通知。

然后,我考虑了父类上的一个属性,类似于IsRead,但这也可能导致竞争条件(在读取属性和订阅就绪事件之间(。

最近做了很多网络方面的事情jQuerysdocument.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
};

这看起来工作得很好,但我想知道是否有a(仍然有可能出现竞争情况,客户没有在这里得到通知,以及b(这个问题或这个实现的更优雅的解决方案?

是的,你仍然可以在这里有一个比赛条件:

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

您可能会遇到IsReady被求值为false的情况,但在更新事件处理程序之前,Init()方法会将IsReady设置为true并激发事件然后上面的第二行运行,事件再也不会被触发。

文档中add关键字的示例显示了lock的使用。这可能是您应该在这里使用的——在addremove访问器中,以及在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);
}

最新更新