Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteAddHostedService does not make a background worker run only once across an ASP.NET Core deployment. Every running application host can start its own hosted-service instance, so multiple replicas may execute the same recurring job. Separately, a timer can begin a new callback before the previous one finishes. Preventing local overlap and preventing overlap across replicas are different problems—and require different coordination.
Why can the same ASP.NET Core job run more than once?
A hosted service runs inside an application host; it is not a cluster-wide scheduler or leader election mechanism. Registering a service with AddHostedService means each running host can start its own copy. If a deployment has several replicas, each may run the same loop or scheduled work unless something coordinates them.
As an Amazon Associate I earn from qualifying purchases.
There is also a separate timer-reentrancy issue. Microsoft Learn warns that “The Timer doesn’t wait for previous executions of DoWork to finish, so the approach shown might not be suitable for every scenario.” A callback that takes longer than the timer interval can therefore overlap with another callback in that same process. Microsoft’s ASP.NET Core hosted-services documentation for .NET 10 describes this behavior.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →- Local overlap: One process starts a second execution while its first is still running.
- Cross-replica overlap: Two or more application instances independently start work that is intended to have one active runner.
A process-local guard such as a SemaphoreSlim, lock, or static flag can address the first case if it is applied correctly. It cannot coordinate other processes or machines. To prevent cross-replica overlap, every potential runner needs to use a shared coordination mechanism or a scheduler/platform feature that provides the required concurrency behavior.
#1 Best Overall
Choose a coordination model that fits the job
Microsoft’s Azure Architecture Center cautions that multiple instances of a background job can compete for shared resources such as databases and storage, affecting contention, availability, and data integrity. It discusses approaches including pessimistic locking, singleton execution, queues, and platform-specific concurrency controls; each involves tradeoffs. See Microsoft’s background-job guidance.
| Approach | Coordination scope | What it suits | Important tradeoff |
|---|---|---|---|
| Process-local guard | One process only | Preventing a timer callback from re-entering within a single host | Does not stop another replica from running the same work. |
| Singleton worker or scheduled runner | One designated runner, if deployment and platform configuration enforce it | A job that must have one active runner and does not require parallel execution | Reduces the redundancy and throughput available from multiple instances; verify how failover and restart are handled. |
| Shared lock or lease | Processes that use the same coordination store | Allowing multiple instances to compete while limiting active ownership | Requires explicit rules for atomic acquisition, ownership, expiry, renewal, crashes, and paused or stale owners. |
| Queue with competing consumers | Consumers draw discrete tasks from a shared queue | Request-triggered or otherwise separable units of work that can be distributed and retried | Persistence, retries, duplicate delivery, idempotency, queue capacity, and downstream limits all matter. |
| Scheduler or platform concurrency control | As provided by the selected platform and its configuration | Scheduled jobs where the platform’s documented behavior matches the deployment need | Semantics are platform-specific; validate the actual configuration rather than assuming that scheduling itself guarantees exclusivity. |
How to prevent overlapping executions
For overlap inside one host
Choose a local mechanism that makes the callback wait, skip, or otherwise handle an execution already in progress. The correct behavior depends on the job: waiting may create a backlog, while skipping may be acceptable for refresh work but not for required transactions. A local guard only protects callers that share that process and guard.
Rank #2
For one active scheduled runner across replicas
Use a scheduler or platform feature with documented cross-instance concurrency semantics. Microsoft cites Azure Functions timer triggers, which use a distributed lock, and Kubernetes CronJobs with concurrencyPolicy: Forbid as examples of concurrency controls. Confirm the relevant behavior and settings for the exact hosting environment; these examples do not mean that an ASP.NET Core hosted service automatically receives the same protection.
Free tools Windows power users keep installed
One-click scans. No signup required.
For request-triggered discrete work
Represent each unit of work as a queue message and let consumers claim tasks. This can distribute load and separate request handling from job execution, but it does not eliminate the need to design for retries and recovery. Make side effects idempotent where possible, and check that queue throughput and downstream services can sustain the consumer rate.
For a shared database lock or lease
A lock or lease is only as reliable as its ownership and failure rules. Before relying on one, specify how acquisition is atomic, how an owner proves it still holds the lock, how expiration and renewal work, what happens after a process crash, and how a paused worker is prevented from continuing after its lease has expired. The general guidance to use locking does not establish the correct implementation for a particular database or library; consult that system’s primary documentation before choosing code or configuration.
For a background-job framework
Hangfire documents distributed locks as part of coordination when running multiple servers. Its documentation describes multiple server instances, and its feature overview also identifies distributed locking. Evaluate its storage and operational model against the system you already run; the existence of distributed locks is not a guarantee of exactly-once completion for every job or external side effect.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Design for retries, crashes, and duplicate effects
Exclusivity and successful completion are separate guarantees. A lock can reduce simultaneous execution, but it cannot by itself ensure exactly-once behavior if a process crashes after making an external change and before recording completion. Likewise, queues and schedulers can involve retries or recovery paths that make repeat execution part of the failure model.
Quick Recap
Best Value
- Applying all key ASP.NET Core components, including MVC for HTML generation, .NET Core, EF Core, ASP.NET Identity, dependency injection, and more
- Integrating ASP.NET Core with leading client-side frameworks, including Bootstrap
- ASP.NET Core code for implementing business logic and data transformations
- Handling configuration, routing, controllers, views, and common tasks (including posting forms and presenting data)
- Performing complementary tasks: error handling, logging, application design, authentication, localization, and more
- Make operations idempotent where possible, so a retry does not apply the same effect twice.
- Define which failures should trigger a retry and how repeated failures are surfaced or recovered.
- For leases, address expiration and stale ownership rather than treating acquisition as permanent proof that a worker remains active.
- Account for shared-store limits and downstream bottlenecks; adding consumers or replicas can increase competition rather than useful throughput.
- Choose persistence and restart behavior that match the cost of losing or repeating a task.
A practical decision path
- Determine the scope. If only callbacks in one process can overlap, use a local guard and select whether overlapping work should wait or be skipped. If replicas must coordinate, a local lock is insufficient.
- Classify the work. For discrete tasks triggered by requests, consider a persistent queue with competing consumers. For a scheduled task requiring one active runner, look for a scheduler or platform concurrency feature documented for your deployment.
- Specify failure behavior. Decide how the system handles crashes, retries, duplicate side effects, lease expiration, and recovery before selecting a lock, queue, or singleton deployment.
- Check the bottleneck and operational cost. Consider the limits of the shared database, queue, and downstream services, as well as the work required to operate the chosen coordination mechanism.
- Validate the guarantee at the right boundary. Confirm that the selected scheduler, framework, store, or deployment setting coordinates all relevant instances—not just threads in one process—and test the failure cases that matter to the job.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




