abpframework/abp · error · ObjectDisposedException
Cannot access a disposed object.
Error message
Cannot access a disposed object.
What it means
Thrown by DefaultDynamicBackgroundWorkerManager.AddAsync as an ObjectDisposedException when attempting to add a dynamic worker after the manager has been disposed (StopAllAsync was called, setting _isDisposed = true). The manager is a singleton that tears down all dynamic workers on shutdown; any add call after that is invalid.
Source
Thrown at framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/DefaultDynamicBackgroundWorkerManager.cs:57
Check.NotNullOrWhiteSpace(workerName, nameof(workerName));
Check.NotNull(schedule, nameof(schedule));
Check.NotNull(handler, nameof(handler));
schedule.Validate();
if (!schedule.CronExpression.IsNullOrWhiteSpace())
{
throw new AbpException(
$"The default in-memory background worker manager does not support CronExpression for dynamic worker '{workerName}'. " +
"Please clear CronExpression and use Period-based scheduling, or use a scheduler-backed provider (Hangfire or Quartz).");
}
await _semaphore.WaitAsync(cancellationToken);
try
{
if (_isDisposed)
{
throw new ObjectDisposedException(nameof(DefaultDynamicBackgroundWorkerManager));
}
if (_dynamicWorkers.TryRemove(workerName, out var existingWorker))
{
await existingWorker.StopAsync(cancellationToken);
Logger.LogInformation("Replaced existing dynamic worker: {WorkerName}", workerName);
}
var worker = CreateDynamicWorker(workerName, schedule, handler);
_dynamicWorkers[workerName] = worker;
await worker.StartAsync(cancellationToken);
}
finally
{
_semaphore.Release();
}
}View on GitHub (pinned to 7ed43b1931)
Solutions
- Check IHostApplicationLifetime.ApplicationStopping before calling AddAsync, and skip registration if the application is shutting down.
- Ensure dynamic worker registration happens during startup or steady-state, not during shutdown.
- In tests, create a fresh manager (or a fresh test host) rather than reusing a disposed one.
Example fix
// before — may race with shutdown
public class MyHostedService : IHostedService
{
public async Task StartAsync(CancellationToken ct)
{
await _dynamicManager.AddAsync("worker", schedule, handler, ct);
}
}
// after — guard against shutdown
public async Task StartAsync(CancellationToken ct)
{
if (_lifetime.ApplicationStopping.IsCancellationRequested) return;
await _dynamicManager.AddAsync("worker", schedule, handler, ct);
} Defensive patterns
Strategy: validation
Validate before calling
if (_lifetime.ApplicationStopping.IsCancellationRequested) return; await dynamicManager.AddAsync(name, schedule, handler, ct);
Type guard
static bool IsSafeToAdd(IHostApplicationLifetime lifetime) => !lifetime.ApplicationStopping.IsCancellationRequested;
Try / catch
try { await dynamicManager.AddAsync(name, schedule, handler, ct); }
catch (ObjectDisposedException) { logger.LogWarning("Dynamic worker manager disposed; skipping AddAsync during shutdown."); } Prevention
- Check IHostApplicationLifetime.ApplicationStopping before dynamic registration calls.
- Register dynamic workers during startup, not during shutdown or teardown.
- In tests, use a fresh manager/host per test to avoid cross-test disposal races.
When it happens
Trigger: Calling IDynamicBackgroundWorkerManager.AddAsync during or after application shutdown (StopAllAsync has run). A background service or hosted service that tries to register a dynamic worker while the host is stopping, racing with the manager's disposal.
Common situations: A hosted service's StopAsync triggers a dynamic worker registration as part of shutdown logic. A long-running operation that outlives host shutdown tries to add a worker. Unit/integration tests that call StopAllAsync and then continue using the same manager instance.
Related errors
- Cannot convert period: {period} to cron expression.
- The default in-memory background worker manager does not sup
- Period must be greater than 0 when provided. Given value: {P
- At least one of 'Period' or 'CronExpression' must be set.
- Cannot convert period: {period} to cron expression, use Hang
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/7cbeba4c07749f8f.
Report an issue: GitHub.