Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
416 changes: 416 additions & 0 deletions .editorconfig

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/KK.DotNet.BackgroundTasks.Scheduled.Web.Sample/bin/Debug/netcoreapp2.2/KK.DotNet.BackgroundTasks.Scheduled.Web.Sample.dll",
"program": "${workspaceFolder}/samples/KK.DotNet.BackgroundTasks.Scheduled.Sample.Web/bin/Debug/netcoreapp2.2/KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.dll",
"args": [],
"cwd": "${workspaceFolder}/src/KK.DotNet.BackgroundTasks.Scheduled.Web.Sample",
"cwd": "${workspaceFolder}/samples/KK.DotNet.BackgroundTasks.Scheduled.Sample.Web",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart",
"launchBrowser": {
Expand Down
2 changes: 1 addition & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "process",
"args": [
"build",
"${workspaceFolder}/src/KK.DotNet.BackgroundTasks.Scheduled.Web.Sample/KK.DotNet.BackgroundTasks.Scheduled.Web.Sample.csproj"
"${workspaceFolder}/samples/KK.DotNet.BackgroundTasks.Scheduled.Sample.Web/KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.csproj"
],
"problemMatcher": "$msCompile","group": {
"kind": "build",
Expand Down
53 changes: 33 additions & 20 deletions KK.DotNet.BackgroundTasks.Scheduled.sln
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7E682FEA-3201-4830-BD41-6260DA4C03D8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KK.DotNet.BackgroundTasks.Scheduled", "src\KK.DotNet.BackgroundTasks.Scheduled\KK.DotNet.BackgroundTasks.Scheduled.csproj", "{57BB4613-E586-4254-8F01-DC7A27494567}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KK.DotNet.BackgroundTasks.Scheduled", "src\KK.DotNet.BackgroundTasks.Scheduled\KK.DotNet.BackgroundTasks.Scheduled.csproj", "{57BB4613-E586-4254-8F01-DC7A27494567}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KK.DotNet.BackgroundTasks.Scheduled.Web.Sample", "src\KK.DotNet.BackgroundTasks.Scheduled.Web.Sample\KK.DotNet.BackgroundTasks.Scheduled.Web.Sample.csproj", "{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A82875E9-6AEE-4483-AFA6-046F057FD3F6}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
global.json = global.json
LICENSE = LICENSE
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{6BED458A-660D-483A-B2E7-B058D5B9BFBF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KK.DotNet.BackgroundTasks.Scheduled.Sample.Web", "samples\KK.DotNet.BackgroundTasks.Scheduled.Sample.Web\KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.csproj", "{178B2AC5-E8C9-408B-B278-60D561256C9E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -18,9 +28,6 @@ Global
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{57BB4613-E586-4254-8F01-DC7A27494567}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{57BB4613-E586-4254-8F01-DC7A27494567}.Debug|Any CPU.Build.0 = Debug|Any CPU
Expand All @@ -34,21 +41,27 @@ Global
{57BB4613-E586-4254-8F01-DC7A27494567}.Release|x64.Build.0 = Release|Any CPU
{57BB4613-E586-4254-8F01-DC7A27494567}.Release|x86.ActiveCfg = Release|Any CPU
{57BB4613-E586-4254-8F01-DC7A27494567}.Release|x86.Build.0 = Release|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Debug|x64.ActiveCfg = Debug|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Debug|x64.Build.0 = Debug|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Debug|x86.ActiveCfg = Debug|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Debug|x86.Build.0 = Debug|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Release|Any CPU.Build.0 = Release|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Release|x64.ActiveCfg = Release|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Release|x64.Build.0 = Release|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Release|x86.ActiveCfg = Release|Any CPU
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8}.Release|x86.Build.0 = Release|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Debug|x64.ActiveCfg = Debug|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Debug|x64.Build.0 = Debug|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Debug|x86.ActiveCfg = Debug|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Debug|x86.Build.0 = Debug|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Release|Any CPU.Build.0 = Release|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Release|x64.ActiveCfg = Release|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Release|x64.Build.0 = Release|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Release|x86.ActiveCfg = Release|Any CPU
{178B2AC5-E8C9-408B-B278-60D561256C9E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{57BB4613-E586-4254-8F01-DC7A27494567} = {7E682FEA-3201-4830-BD41-6260DA4C03D8}
{0FC375DB-728A-4D99-9B6E-16FF1ABBD5D8} = {7E682FEA-3201-4830-BD41-6260DA4C03D8}
{178B2AC5-E8C9-408B-B278-60D561256C9E} = {6BED458A-660D-483A-B2E7-B058D5B9BFBF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {718CBEA0-7FDE-4933-9D3D-BA633B48AE4D}
EndGlobalSection
EndGlobal
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ This project contains the code for the NuGet Package to get scheduled tasks in a

## Usage

> **INFO**: For detailed usage information please have a look in the `KK.DotNet.BackgroundTasks.Scheduled.Web.Sample` project.

### Task

You can add multiple tasks in your projekt. The task has to implement the `IScheduledTask` interface.
Expand Down Expand Up @@ -70,13 +68,30 @@ services.AddSingleton<IScheduledTaskOptions<SampleTask>>(

### SchedulerHost

**After** the registration of all your tasks there is only one thing left to do.
Register the `SchedulerHostedService` like so:
After the registration of all your tasks there is only one thing left to do.
Register the `SchedulerHostedService` in your `Startup.cs` like so:

```C#
services.AddScheduler();
```

If a custom implemented scheduler should be used, use this kind of registration:

```C#
services.AddHostedService<SchedulerHostedService>();
services.AddHostedService<CustomSchedulerHostedService>();
```

`CustomSchedulerHostedService` must implement `ISchedulerHostedService`.

### Scheduler

When using the default SchedulerHostedService than there is also a `Scheduler`.
This can be used to get access to the scheduled task list for example.

### Sample

You can find a sample how to get this working in the `samples` folder. Please have a look there and read the comments.

## NuGet

| Feed | Name | Status |
Expand Down
4 changes: 2 additions & 2 deletions global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"sdk": {
"version": "2.2.105"
"version": "2.2.401"
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update to newest version

}
}
}
8 changes: 8 additions & 0 deletions omnisharp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"RoslynExtensionsOptions": {
"enableAnalyzersSupport": true
},
"FormattingOptions": {
"enableEditorConfigSupport": true
}
}
6 changes: 3 additions & 3 deletions pipelines/KK.DotNet.BackgroundTasks.Scheduled.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ variables:
BuildConfiguration: "Release"
Project: "$(Build.SourcesDirectory)/src/KK.DotNet.BackgroundTasks.Scheduled/KK.DotNet.BackgroundTasks.Scheduled.csproj"
ProjectFolder: "$(Build.SourcesDirectory)/src/KK.DotNet.BackgroundTasks.Scheduled"
DotNetVersion: "2.2.105"
GitVersion: "4.0.1-beta1-62"
DotNetVersion: "2.2.401"
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the new SDK from global.json

GitVersion: "5.0.1"

name: $(Year:yy)$(DayOfYear)$(Rev:rr)

Expand Down Expand Up @@ -85,4 +85,4 @@ steps:
inputs:
pathtoPublish: "$(Build.ArtifactStagingDirectory)"
artifactName: NuGet
parallel: true
parallel: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.Backgroundservices
{
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
using KK.DotNet.BackgroundTasks.Scheduled;

public class RuntimeSampleTask : IScheduledTask
{
private readonly ILogger<RuntimeSampleTask> logger;

public RuntimeSampleTask(
IScheduledTaskOptions<RuntimeSampleTask> options,
ILogger<RuntimeSampleTask> logger
)
{
this.Options = options;
this.logger = logger;
}

public IScheduledTaskOptions<IScheduledTask> Options { get; }

public async Task ExecuteAsync(CancellationToken stoppingToken)
{
this.logger.LogDebug("Runtime Sample Task started");

_ = stoppingToken.Register(() => this.logger.LogDebug("Runtime Sample Task forced stopping."));

var runCount = 0;
while (runCount < 5)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I'd prefer a for-loop, but i assume thats a matter of style.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, I will change this.

{
if (stoppingToken.IsCancellationRequested)
{
// Task was killed from outside.
this.logger.LogDebug($"{System.DateTime.Now} Runtime Sample Task cancellation requested!");
return;
}

this.logger.LogDebug($"{System.DateTime.Now} Runtime Sample Task loop {runCount}");
await Task.Delay(1000, stoppingToken);
runCount++;
}

this.logger.LogDebug("Runtime Sample Task is finished");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
namespace KK.DotNet.BackgroundTasks
namespace KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.Backgroundservices
{
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -25,7 +24,7 @@ public async Task ExecuteAsync(CancellationToken stoppingToken)
{
this.logger.LogDebug("Sample Task started");

stoppingToken.Register(() => this.logger.LogDebug("Sample Task forced stopping."));
_ = stoppingToken.Register(() => this.logger.LogDebug("Sample Task forced stopping."));

var runCount = 0;
while (runCount < 5)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
namespace KK.DotNet.BackgroundTasks
namespace KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.Backgroundservices
{
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -25,7 +24,7 @@ public async Task ExecuteAsync(CancellationToken stoppingToken)
{
this.logger.LogDebug("Super Sample Task started");

stoppingToken.Register(() => this.logger.LogDebug("Super Sample Task forced stopping."));
_ = stoppingToken.Register(() => this.logger.LogDebug("Super Sample Task forced stopping."));

this.logger.LogDebug($"{System.DateTime.Now} Super Sample Task is running in background");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@


<ItemGroup>
<ProjectReference Include="..\KK.DotNet.BackgroundTasks.Scheduled\KK.DotNet.BackgroundTasks.Scheduled.csproj" />
<ProjectReference Include="..\..\src\KK.DotNet.BackgroundTasks.Scheduled\KK.DotNet.BackgroundTasks.Scheduled.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@model ErrorViewModel
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}
Expand All @@ -15,7 +16,7 @@

<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.Pages
{
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class ErrorModel : PageModel
{
public string RequestId { get; set; }

public bool ShowRequestId => !string.IsNullOrEmpty(this.RequestId);

public void OnGet()
=> this.RequestId = Activity.Current?.Id ?? this.HttpContext.TraceIdentifier;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
<p>Scheduled Tasks running: @Model.Scheduler.Tasks.Count</p>
@foreach (var task in @Model.Scheduler.Tasks)
{
<p><strong>Name</strong>: @task.Name <br /><strong>NextStartTime</strong>: @task.NextStartTime</p>
}
<form method="POST">
<div>Name: <input asp-for="Options.Name" /></div>
<div>Name: <input asp-for="Options.Schedule" /></div>
<input value="Add Task" type="submit" />
</form>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
namespace KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.Pages
{
using System.Threading.Tasks;
using KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.Backgroundservices;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

public class IndexModel : PageModel
{
private readonly ILogger<RuntimeSampleTask> runtimeSampleTaskLogger;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also matter of preference but: since almost all classes only have one logger, I call them all the same: "logger". I only call them differently if there are different loggers in a given class to make myself and others aware that this might not be the logger one wants to use. Also, the shorter name might allow you to put the parameters in lines 22ff on a single line.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point, I will change that.


public Scheduler Scheduler { get; }


[BindProperty]
public ScheduledTaskOptions<RuntimeSampleTask> Options { get; set; }

// When using the default SchedulerHostedService than there is also a Scheduler
// this can be used to get access to the scheduled task list for example
public IndexModel(
Scheduler scheduler,
ILogger<RuntimeSampleTask> runtimeSampleTaskLogger
)
{
this.Scheduler = scheduler;
this.runtimeSampleTaskLogger = runtimeSampleTaskLogger;
this.Options = new ScheduledTaskOptions<RuntimeSampleTask>()
{
Name = "Awesome Runntime Task",
Schedule = "*/15 * * * *"
};
}

public void OnGet()
{
//this.Scheduler.SchedulerTasks;
}

public IActionResult OnPost()
{
if (!this.ModelState.IsValid)
{
return this.Page();
}

this.Scheduler.AddTask(new RuntimeSampleTask(this.Options, this.runtimeSampleTaskLogger));

return this.Page();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
@{
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace KK.DotNet.BackgroundTasks.Scheduled.Sample.Web.Pages
{
using Microsoft.AspNetCore.Mvc.RazorPages;

public class PrivacyModel : PageModel
{
public void OnGet()
{
}
}
}
Loading