# Run a Worker - .NET SDK

> Create and run a Temporal Worker using the .NET SDK.

This page covers long-lived Workers that you host and run as persistent processes.
For Workers that run on serverless compute like AWS Lambda, see [Serverless Workers](/develop/dotnet/workers/serverless-workers).

## Create and run a Worker 

Create a `TemporalWorker` with a Temporal Client and a `TemporalWorkerOptions` that names the Task Queue to poll.
Add the Workflows and Activities the Worker can execute, then call `ExecuteAsync()` to start polling.

<!--SNIPSTART dotnet-create-worker-->
[features/snippets/worker/worker.cs](https://github.com/temporalio/features/blob/main/features/snippets/worker/worker.cs)
```cs
var options = new TemporalWorkerOptions("my-task-queue");
options.AddWorkflow<GreetingWorkflow>();
options.AddAllActivities(typeof(GreetingActivities), null);

using var worker = new TemporalWorker(client, options);
await worker.ExecuteAsync(CancellationToken.None);
```
<!--SNIPEND-->

`ExecuteAsync()` takes a `CancellationToken` and polls until that token is cancelled.
The snippet passes `CancellationToken.None`, which never cancels, so the Worker runs until the process exits.
To stop a Worker on demand, pass a token you control instead. See [Shut down a Worker](#shut-down-a-worker).

`TemporalWorker` implements `IDisposable`, so declare it with `using` to release its resources when the process exits.

## Register Workflows and Activities 

All Workers listening to the same Task Queue must be registered to handle the same Workflow Types and Activity Types.
If a Worker polls a Task for a type it does not know about, the Task fails. The Workflow Execution itself does not fail.

Add Workflows with `AddWorkflow<T>()` and Activities with `AddActivity()` or `AddAllActivities()`:

```csharp
var options = new TemporalWorkerOptions("my-task-queue");
options.AddWorkflow<GreetingWorkflow>();
options.AddWorkflow<OrderWorkflow>();
options.AddAllActivities(new MyActivities(databaseClient));
```

`AddAllActivities()` registers every method marked with `[Activity]`. Pass an instance to register instance methods, which lets Activities share state such as a database client. For a class of static Activity methods, pass the type and `null` instead.

## Connect to Temporal Cloud 

To run a Worker against Temporal Cloud, configure the Client connection with your Namespace address and authentication credentials.
See [Connect to Temporal Cloud](/develop/dotnet/client/temporal-client#connect-to-temporal-cloud) for setup instructions.

## Configure Worker options 

`TemporalWorkerOptions` controls concurrency limits, pollers, timeouts, and caching, including `MaxConcurrentActivities`, `MaxConcurrentWorkflowTasks`, and `MaxCachedWorkflows`.
The defaults work for most cases.

To tune these values against real load, see [Worker performance](/develop/worker-performance) and the [Worker tuning reference](/develop/worker-tuning-reference).

## Run a versioned Worker 

Set a Worker Deployment Version and enable versioning in `DeploymentOptions`, then set a versioning behavior on each Workflow.

<!--SNIPSTART dotnet-versioned-worker-->
[features/snippets/worker/worker.cs](https://github.com/temporalio/features/blob/main/features/snippets/worker/worker.cs)
```cs
var options = new TemporalWorkerOptions("my-task-queue")
{
    DeploymentOptions = new WorkerDeploymentOptions(
        new WorkerDeploymentVersion("my-app", "1.0"),
        useWorkerVersioning: true),
};
options.AddWorkflow<VersionedGreetingWorkflow>();
options.AddAllActivities(typeof(GreetingActivities), null);

using var worker = new TemporalWorker(client, options);
```
<!--SNIPEND-->

Set the behavior per Workflow with `[Workflow(VersioningBehavior = VersioningBehavior.Pinned)]`, or set a default for the whole Worker with `DefaultVersioningBehavior` on `WorkerDeploymentOptions`.
`VersioningBehavior` comes from the `Temporalio.Common` namespace.

A versioning behavior applies only to a Worker that has versioning enabled.
If a Workflow declares one and its Worker does not enable versioning, the server rejects the Workflow Task and the Task retries instead of failing outright.

See [Worker Versioning](/worker-versioning) for the available versioning behaviors and how new versions roll out.

## Shut down a Worker 

To stop a Worker on demand, start it with a token you can cancel yourself instead of `CancellationToken.None`.
Create a `CancellationTokenSource`, pass its `Token` to `ExecuteAsync()`, then cancel the source when the Worker should stop, such as from a `Console.CancelKeyPress` handler.
The Worker stops polling for new Tasks and waits for in-flight Tasks to finish, up to `GracefulShutdownTimeout`.

<!--SNIPSTART dotnet-worker-graceful-shutdown-->
[features/snippets/worker/worker.cs](https://github.com/temporalio/features/blob/main/features/snippets/worker/worker.cs)
```cs
using var tokenSource = new CancellationTokenSource();
Console.CancelKeyPress += (_, eventArgs) =>
{
    tokenSource.Cancel();
    eventArgs.Cancel = true;
};

var options = new TemporalWorkerOptions("my-task-queue")
{
    GracefulShutdownTimeout = TimeSpan.FromSeconds(30),
};
options.AddWorkflow<GreetingWorkflow>();

using var worker = new TemporalWorker(client, options);
await worker.ExecuteAsync(tokenSource.Token);
```
<!--SNIPEND-->

`ExecuteAsync()` throws `OperationCanceledException` once the Worker stops, so catch it where you want the process to exit cleanly.
See [Worker shutdown](/encyclopedia/workers/worker-shutdown) for what happens to in-flight Workflow Tasks and Activities.

## Run a Worker with dependency injection 

The [Temporalio.Extensions.Hosting](https://github.com/temporalio/sdk-dotnet/tree/main/src/Temporalio.Extensions.Hosting) package registers a Worker as a hosted service, so the .NET host owns its lifecycle and Activities resolve their dependencies from the service provider.

```csharp
var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(ctx =>
        ctx.
            AddScoped<IMyDatabaseClient, MyDatabaseClient>().
            AddHostedTemporalWorker(
                clientTargetHost: "localhost:7233",
                clientNamespace: "default",
                taskQueue: "my-task-queue").
            AddScopedActivities<MyActivities>().
            AddWorkflow<MyWorkflow>())
    .Build();
await host.RunAsync();
```

Scoped Activities get a new instance per Activity Execution, so each one receives its own scoped dependencies.
