C# 像document.ready-Event一样实现jQuery

C# 像document.ready-Event一样实现jQuery,c#,events,asp.net-core,C#,Events,Asp.net Core,我正在创建一个asp.net core应用程序,它使用asp.net core 2.1的新HostedService功能。通过services.AddHostedService()注册的一些服务依赖于其他服务,我正在寻找在“父服务”准备就绪时通知“子服务”的方法 我的第一个实现如下所示: // Parent class public delegate void OnServiceReadyHandler(object sender); public event OnServiceReadyHan

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

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

最近我想到了做很多网络工作。它在文档准备就绪后激发,如果文档已处于就绪状态,则立即激发。我将我的实现更改为:

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

你为什么不按正确的顺序注册你的服务,以确保它们可以相互依赖?或者,为此使用orchestrator服务。但我不会在这里添加事件处理。如果您不想在实际上还有事情要做的情况下生成一个服务报告说它已经准备好了,那么不要让它完成启动任务。