dotnet / dotnet/aspnetcore

Ihosted service Task hosted in IIS process is not triggering StopAsync while performing IISreset

Open
#57,248 2 comments 1 reaction 0 assignees View on GitHub
area-networking Author: Migration Bot :robot: feature-iis
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

_This issue has been moved from [a ticket on Developer Community](https://developercommunity.visualstudio.com/t/Ihosted-service-Task-hosted-in-IIS-proce/10717550)._

---
[severity:It bothers me. A fix would be nice]
I had create a small Ihosted service and deployed into server as IIS. and when I perform the apppool stop or iis reset, I am expecting the stop async to be called but its not happening. Please find below the code snippet and the Server specification.

```
Server Spec : Windows Server 2016 Standard
IIS :
version 10
Site PreLoadEnabled to true
Recycling.periodicRestart.time = 0
App Pool start up mode to AlwaysRunning
```

```csharp
namespace TaskRunIhosted
{
public class QueueProcessingService : IHostedLifecycleService
{
private readonly ITaskLogger _logger;
private Task _executingTask;

private CancellationTokenSource _stoppingCts = new CancellationTokenSource();

public QueueProcessingService(ITaskLogger messageQueueClient)
{
_logger = messageQueueClient;
}

public async Task StartingAsync(CancellationToken cancellationToken)
{
_logger. LogInformation($"StartingAsync .... Performed...");
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
}

public async Task StartAsync(CancellationToken cancellationToken)
{
_logger. LogInformation($"StartAsync .... Performed...");
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
// Triggered when the application host is ready to start the service.
_executingTask = ExecuteAsync(_stoppingCts.Token);

// If the task is completed, return it, otherwise it's still running
await (_executingTask.IsCompleted ? _executingTask : Task.CompletedTask);
}

protected async Task ExecuteAsync(CancellationToken stoppingToken)
{
// The main background processing logic goes here
while (!stoppingToken.IsCancellationRequested)
{
_logger. LogInformation($"ExecuteAsync .... Performed...");

await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);

//var message = await _logger. ReceiveAsync(stoppingToken);
//if (message != null)
//{
// ProcessMessage(message);
//}
}
_logger. LogInformation($"IsCancellationRequested .... Performed...");
}

public Task StartedAsync(CancellationToken cancellationToken)
{
_logger. LogInformation($"StartedAsync .... Performed...");

// Logic after StartAsync, e.g., post-initialization logging or actions
// This is where you might log that the service has successfully started
return Task.CompletedTask;
}

public Task StoppingAsync(CancellationToken cancellationToken)
{
_logger. LogInformation($"StoppingAsync .... Performed...");

// Logic before StopAsync, e.g., pre-cleanup actions
// This is where you might log that the service is stopping
return Task.CompletedTask;
}

public async Task StopAsync(CancellationToken cancellationToken)
{
_logger. LogInformation($"StopAsync .... Performed...");
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
// Triggered when the application host is performing a graceful shutdown.
_stoppingCts.Cancel();

// Wait until the task completes or the stop token triggers
await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, cancellationToken));
}

public async Task StoppedAsync(CancellationToken cancellationToken)
{
_logger. LogInformation($"StoppedAsync .... Performed...");
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
// Logic after StopAsync, e.g., cleaning up the queue
//await _logger. CleanupAsync(cancellationToken);
}

//private void ProcessMessage(QueueMessage message)
//{
// // Process the message, e.g., enriching data, sending notifications, etc.
//}
}
}

namespace TaskRunIhosted;

public class TaskLogger : ITaskLogger
{
private readonly ILogger _logger;

public TaskLogger(ILogger logger)
{
_logger = logger;
}

public void LogInformation(string message)
{
_logger. LogInformation(message);
}
}
```

program.cs
------------------------------------------------------------

```csharp
using Serilog;
using TaskRunIhosted;

var builder = WebApplication.CreateBuilder();
var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
builder. Configuration
. SetBasePath(AppContext.BaseDirectory)
. AddJsonFile($"appsettings.{ env}.json", false, true);

builder. Services.AddSingleton();

builder. Services.AddHostedService();

Log.Logger = new LoggerConfiguration()
. WriteTo.Console(). WriteTo
. File("Logs/logs.txt", rollingInterval: RollingInterval.Day)
. CreateLogger();

builder. Host.UseSerilog();
var app = builder. Build();

app. Run();
```

---
### Original Comments

#### Feedback Bot on 8/7/2024, 01:57 AM:

(private comment, text removed)
#### Babin Bharathan on 8/9/2024, 00:39 AM:

(private comment, text removed)

---
### Original Solutions
(no solutions)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.