Search code examples
azure-service-fabric

Service Fabric -- CreateServiceInstanceListeners -- Multiple Listeners -- "yield return" or "return new[]"


If your Service Fabric service has multiple listeners, I have noticed that you can create the CreateServiceInstanceListeners using 2 different patterns. (.Net Framework / Statefull / Stateless)

The first method is yielding returns while the second one is returning an array.

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    yield return new ServiceInstanceListener(serviceContext => new OwinCommunicationListener(Startup.ConfigureApp, serviceContext, ServiceEventSource.Current, "ServiceEndpoint")),
    yield return new ServiceInstanceListener(wcfContext => new WcfCommunicationListener<IWebApi>(wcfServiceObject: this, serviceContext: wcfContext,endpointResourceName: "WcfEndpoint",listenerBinding: WcfUtility.CreateTcpListenerBinding()),"WcfEndpoint")
}

versus

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new[]
    {
        new ServiceInstanceListener(serviceContext => new OwinCommunicationListener(Startup.ConfigureApp, serviceContext, ServiceEventSource.Current, "ServiceEndpoint")),
        new ServiceInstanceListener(wcfContext => new WcfCommunicationListener<IWebApi>(wcfServiceObject: this, serviceContext: wcfContext,endpointResourceName: "WcfEndpoint",listenerBinding: WcfUtility.CreateTcpListenerBinding()),"WcfEndpoint")
    };
}

Is there any advantage of using one over the other?


Solution

  • There is no big difference. The returned enumerable is iterated once per service instance.

    Here is the code snipped from sources on GitHub.

    if (this.instanceListeners == null)
    {
        this.instanceListeners = this.userServiceInstance.CreateServiceInstanceListeners();
    }
    
    var endpointsCollection = new ServiceEndpointCollection();
    var listenerOpenedCount = 0;
    
    foreach (var entry in this.instanceListeners)
    {
        var communicationListener = entry.CreateCommunicationListener(this.serviceContext);
        this.AddCommunicationListener(communicationListener);
        var endpointAddress = await communicationListener.OpenAsync(cancellationToken);
        endpointsCollection.AddEndpoint(entry.Name, endpointAddress);
        listenerOpenedCount++;
    
        var traceMsg = entry.Name.Equals(ServiceInstanceListener.DefaultName)
            ? "Opened communication listener with default name."
            : $"Opened communication listener with name {entry.Name}.";
    
        ServiceTrace.Source.WriteInfoWithId(TraceType, this.traceId, traceMsg);
    }