Skip to content

Commit 3ad48bc

Browse files
author
Anton Wieslander
committed
channels
1 parent e475368 commit 3ad48bc

File tree

13 files changed

+416
-0
lines changed

13 files changed

+416
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30011.22
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HowToUseChannels", "HowToUseChannels\HowToUseChannels.csproj", "{7AF8688C-D651-40D2-9914-061620DEFABA}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{7AF8688C-D651-40D2-9914-061620DEFABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{7AF8688C-D651-40D2-9914-061620DEFABA}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{7AF8688C-D651-40D2-9914-061620DEFABA}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{7AF8688C-D651-40D2-9914-061620DEFABA}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {5BBB6AC5-E002-45A8-9424-586F8F6A5E0C}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using HowToUseChannels.Serivces;
2+
using Microsoft.AspNetCore.Mvc;
3+
using System.Threading.Channels;
4+
using System.Threading.Tasks;
5+
6+
namespace HowToUseChannels.Controllers
7+
{
8+
public class Home : Controller
9+
{
10+
public IActionResult Send()
11+
{
12+
Task.Run(() =>
13+
{
14+
Task.Delay(100).Wait();
15+
16+
Task.Delay(200).Wait();
17+
});
18+
19+
return Ok();
20+
}
21+
22+
public Task<bool> SendB([FromServices] Notifications notifications)
23+
{
24+
return notifications.Send();
25+
}
26+
27+
public bool SendA([FromServices] Notifications notifications)
28+
{
29+
return notifications.SendA();
30+
}
31+
32+
public async Task<bool> SendC([FromServices] Channel<string> channel)
33+
{
34+
await channel.Writer.WriteAsync("Hello");
35+
return true;
36+
}
37+
}
38+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
9+
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.3" />
10+
</ItemGroup>
11+
12+
</Project>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Microsoft.AspNetCore.Hosting;
6+
using Microsoft.Extensions.Configuration;
7+
using Microsoft.Extensions.Hosting;
8+
using Microsoft.Extensions.Logging;
9+
10+
namespace HowToUseChannels
11+
{
12+
public class Program
13+
{
14+
public static void Main(string[] args)
15+
{
16+
CreateHostBuilder(args).Build().Run();
17+
}
18+
19+
public static IHostBuilder CreateHostBuilder(string[] args) =>
20+
Host.CreateDefaultBuilder(args)
21+
.ConfigureWebHostDefaults(webBuilder =>
22+
{
23+
webBuilder.UseStartup<Startup>();
24+
});
25+
}
26+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace HowToUseChannels.Serivces.Data
8+
{
9+
public class User
10+
{
11+
public int Id { get; set; }
12+
public string Message { get; set; }
13+
}
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using HowToUseChannels.Serivces.Data;
2+
using Microsoft.EntityFrameworkCore;
3+
using System.Threading.Tasks;
4+
5+
namespace HowToUseChannels.Serivces
6+
{
7+
public class Database : DbContext
8+
{
9+
public Database(DbContextOptions<Database> options) : base(options) { }
10+
11+
public DbSet<User> Users { get; set; }
12+
}
13+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Microsoft.Extensions.Hosting;
4+
using Microsoft.Extensions.Logging;
5+
using System;
6+
using System.Net.Http;
7+
using System.Threading;
8+
using System.Threading.Channels;
9+
using System.Threading.Tasks;
10+
11+
namespace HowToUseChannels.Serivces
12+
{
13+
public class NotificationDispatcher : BackgroundService
14+
{
15+
private readonly Channel<string> channel;
16+
private readonly ILogger<NotificationDispatcher> logger;
17+
private readonly IHttpClientFactory httpClientFactory;
18+
private readonly IServiceProvider provider;
19+
20+
public NotificationDispatcher(
21+
Channel<string> channel,
22+
ILogger<NotificationDispatcher> logger,
23+
IHttpClientFactory httpClientFactory,
24+
IServiceProvider provider)
25+
{
26+
this.channel = channel;
27+
this.logger = logger;
28+
this.httpClientFactory = httpClientFactory;
29+
this.provider = provider;
30+
}
31+
32+
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
33+
{
34+
while (!channel.Reader.Completion.IsCompleted) // if not complete
35+
{
36+
// read from channel
37+
var msg = await channel.Reader.ReadAsync();
38+
try
39+
{
40+
using (var scope = provider.CreateScope())
41+
{
42+
var database = scope.ServiceProvider.GetRequiredService<Database>();
43+
if (!await database.Users.AnyAsync())
44+
{
45+
database.Users.Add(new Data.User());
46+
await database.SaveChangesAsync();
47+
}
48+
49+
var user = await database.Users.FirstOrDefaultAsync();
50+
51+
var client = httpClientFactory.CreateClient();
52+
var response = await client.GetStringAsync("https://docs.microsoft.com/en-us/dotnet/core/");
53+
user.Message = response;
54+
55+
await database.SaveChangesAsync();
56+
}
57+
}
58+
catch (Exception e)
59+
{
60+
logger.LogError(e, "notification failed");
61+
}
62+
}
63+
}
64+
}
65+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using System;
3+
using System.Net.Http;
4+
using System.Threading.Tasks;
5+
6+
namespace HowToUseChannels.Serivces
7+
{
8+
public class Notifications
9+
{
10+
private readonly Database database;
11+
private readonly IHttpClientFactory httpClientFactory;
12+
13+
public Notifications(Database database, IHttpClientFactory httpClientFactory)
14+
{
15+
this.database = database;
16+
this.httpClientFactory = httpClientFactory;
17+
}
18+
19+
public async Task<bool> Send()
20+
{
21+
if (!await database.Users.AnyAsync())
22+
{
23+
database.Users.Add(new Data.User());
24+
await database.SaveChangesAsync();
25+
}
26+
27+
var user = await database.Users.FirstOrDefaultAsync();
28+
29+
var client = httpClientFactory.CreateClient();
30+
var response = await client.GetStringAsync("https://docs.microsoft.com/en-us/dotnet/core/");
31+
user.Message = response;
32+
33+
await database.SaveChangesAsync();
34+
35+
return true;
36+
}
37+
38+
public bool SendA()
39+
{
40+
Task.Run(async () =>
41+
{
42+
try
43+
{
44+
if (!await database.Users.AnyAsync())
45+
{
46+
database.Users.Add(new Data.User());
47+
await database.SaveChangesAsync();
48+
}
49+
50+
var user = await database.Users.FirstOrDefaultAsync();
51+
52+
var client = httpClientFactory.CreateClient();
53+
var response = await client.GetStringAsync("https://docs.microsoft.com/en-us/dotnet/core/");
54+
user.Message = response;
55+
56+
await database.SaveChangesAsync();
57+
}
58+
catch (Exception e)
59+
{
60+
var a = e;
61+
}
62+
});
63+
64+
return true;
65+
}
66+
67+
}
68+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using HowToUseChannels.Serivces;
2+
using Microsoft.AspNetCore.Builder;
3+
using Microsoft.AspNetCore.Hosting;
4+
using Microsoft.EntityFrameworkCore;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.Hosting;
7+
using System.Threading.Channels;
8+
9+
namespace HowToUseChannels
10+
{
11+
public class Startup
12+
{
13+
public void ConfigureServices(IServiceCollection services)
14+
{
15+
services.AddDbContext<Database>(config =>
16+
config.UseInMemoryDatabase("test"));
17+
18+
services.AddHttpClient();
19+
20+
services.AddHostedService<NotificationDispatcher>();
21+
services.AddSingleton(Channel.CreateUnbounded<string>());
22+
services.AddTransient<Notifications>();
23+
services.AddControllers();
24+
}
25+
26+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
27+
{
28+
if (env.IsDevelopment())
29+
{
30+
app.UseDeveloperExceptionPage();
31+
}
32+
33+
app.UseRouting();
34+
35+
app.UseEndpoints(endpoints =>
36+
{
37+
endpoints.MapDefaultControllerRoute();
38+
});
39+
}
40+
}
41+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft": "Warning",
6+
"Microsoft.Hosting.Lifetime": "Information"
7+
}
8+
}
9+
}

0 commit comments

Comments
 (0)