我正在创建一个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)对于此问题或此实现的更优雅的解决方案?>
答案 0 :(得分:1)
是的,您仍然可以在这里保持比赛条件:
if (!IsReady)
onServiceReadyHandler = (OnServiceReadyHandler)Delegate.Combine(onServiceReadyHandler, value);
您可能遇到将IsReady
评估为false
的情况,但是在可以更新事件处理程序之前,Init()
方法将IsReady
设置为{{1}并触发该事件。 然后上面的第二行运行,该事件再也不会触发。
example in the documentation for the add
keyword显示lock
的用法。这可能是您应该在这里使用的-在true
和add
访问器中,以及您的remove
方法中。
此外,您在这里使用Init()
的原因是什么?文档只是显示您可以使用Delegate.Combine()
。
+=