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

  1. Check IHostApplicationLifetime.ApplicationStopping before calling AddAsync, and skip registration if the application is shutting down.
  2. Ensure dynamic worker registration happens during startup or steady-state, not during shutdown.
  3. 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

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


AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13). Data as JSON: /api/errors/7cbeba4c07749f8f. Report an issue: GitHub.