3

I have a class that uses the EventHubClient (Microsoft.Azure.EventHubs) to connect to an Azure EventHub. I use a method on the class that sends events to the EventHub and after I'm done, I want to close the connection to the event hub. Is this a case to use the Finalizer?

using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.EventHubs;

public class EventHubSender
{
    private readonly string hubName;
    private readonly string connectionString;
    private readonly EventHubClient eventHubClient;

    public EventHubSender(string hubName, string connectionString)
    {
        this.hubName = hubName;
        this.connectionString = connectionString;

        // Create client
        var connectionStringBuilder = new EventHubsConnectionStringBuilder(this.connectionString)
        {
            EntityPath = this.hubName
        };
        this.eventHubClient = EventHubClient.CreateFromConnectionString(connectionStringBuilder.ToString());
    }

    ~EventHubSender()
    {
        // Close the client
        this.eventHubClient.Close();
    }

    public async Task SendMessage(string value)
    {
        // Create the data
        var eventData = new EventData(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)));

        // Send message
        await this.eventHubClient.SendAsync(eventData);
    }
}

The class EventHubSender could instantiated for each EventHub I want to send data to and the SendMessage method could be called n times. I want to close the client entity but don't want to rely on the developer to call a method to close it.

I think part of the issue if I'm not sure where the EventHubClient sits, whether it is a managed or unmanaged object. I've read this to try and gain an understanding, and also looked at the answers here but I think this specific case for Azure still warrants a question.

SubjectiveKirby
  • 168
  • 1
  • 15
  • 3
    It is not formally correct, Microsoft docs strongly warn to never do this. Finalization order is non-deterministic, so the eventHubClient object might have already been finalized and calling its Close() method might blow up badly. Or not. Hard to test because you can't control order. Proper way *is* to implement IDisposable and put your fate in the hands of the programmers you don't trust. – Hans Passant Jul 06 '18 at 14:18

1 Answers1

0

No, it is not safe to close this object in a finalizer. The EventHubClient may get finalized before the EventHubSender.

To clean up managed objects like EventHubClient, implement IDisposable or IAsyncDisposable in your wrapper and close the EventHubClient in your dispose method.

If the caller forgets to dispose EventHubSender, then you have to trust that EventHubClient implements its own finalizer that closes any unmanaged resources it owns. If it doesn't, then it's a bug in EventHubClient and that class needs to fix it.

Stephen Jennings
  • 12,494
  • 5
  • 47
  • 66