I have a class called ServiceBusBackgroundJobManager
, it sends messages to Azure service bus
public class ServiceBusBackgroundJobManager : BackgroundWorkerBase, IBackgroundJobManager
{
private readonly IAppConfigurationAccessor _configurationAccessor;
private readonly ServiceBusClient _client;
private ServiceBusSender _sender;
private readonly string _serviceBusQueueName;
public ServiceBusBackgroundJobManager(IAppConfigurationAccessor configurationAccessor)
{
_configurationAccessor = configurationAccessor;
var connectionString = _configurationAccessor.Configuration["Abp:ServiceBusConnectionString"];
_serviceBusQueueName = _configurationAccessor.Configuration["Abp:ServiceBusQueueName"];
_client = new ServiceBusClient(connectionString);
}
public async Task<string> EnqueueAsync<TJob, TArgs>(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal,
TimeSpan? delay = null) where TJob : IBackgroundJobBase<TArgs>
{
var messageBody = JsonSerializer.Serialize(args);
var message = new ServiceBusMessage(Encoding.UTF8.GetBytes(messageBody))
{
MessageId = Guid.NewGuid().ToString(),
ContentType = "application/json"
};
if (delay != null)
{
message.ScheduledEnqueueTime = DateTimeOffset.UtcNow.Add(delay.Value);
}
_sender = _client.CreateSender(_serviceBusQueueName);
using var messageBatch = await _sender.CreateMessageBatchAsync();
if (!messageBatch.TryAddMessage(message))
{
throw new Exception($"Exception");
}
try
{
await _sender.SendMessagesAsync(messageBatch);
}
finally
{
await _sender.DisposeAsync();
await _client.DisposeAsync();
}
return string.Empty;
}
}
}
The problem is that in the finally
block I have dispose
, but it will not disposed of in 2 options
- So if two or more jobs are about to be enqueued, the second one won’t have a client to use.
- If no jobs are enqueued, the client doesn’t get disposed.
How I need to write code, to make it works in those 2 options?
2
Answers
You may consider using your resources with in using blocks as you did for
messageBatch
.See this link for more information: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/using
Do you need to create the sender every time? It’s safe to cache the sender or use a singleton for the lifetime of the application. https://learn.microsoft.com/en-us/dotnet/api/azure.messaging.servicebus.servicebussender?view=azure-dotnet