Skip to content

Commit 502c7b7

Browse files
Merge branch 'main' into seo/84966-replace-whitespaces-string-csharp
2 parents 2598163 + dbf6bbe commit 502c7b7

118 files changed

Lines changed: 1617 additions & 668 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎aspnetcore-features/HttpClientDefaultAndPerRequestTimeOut/HttpClientDefaultAndPerRequestTimeOut/HttpClientDefaultAndPerRequestTimeOut.csproj‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
5-
<Nullable>disable</Nullable>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<Nullable>enable</Nullable>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<UserSecretsId>d0d8591a-b364-4f96-921f-d24a0e638079</UserSecretsId>
8-
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
9-
<DockerfileContext>.</DockerfileContext>
108
</PropertyGroup>
119

1210
<ItemGroup>
13-
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
11+
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="10.10.0" />
1412
</ItemGroup>
1513

1614
<ItemGroup>

‎aspnetcore-features/HttpClientDefaultAndPerRequestTimeOut/HttpClientDefaultAndPerRequestTimeOut/Program.cs‎

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
1-
using Microsoft.AspNetCore.Builder;
2-
using Microsoft.AspNetCore.Mvc;
3-
using System.Net.Http;
4-
using System.Threading;
5-
61
var builder = WebApplication.CreateBuilder(args);
72

8-
// Add services to the container.
9-
10-
builder.Services.AddControllers();
11-
123
builder.Services.AddHttpClient("TestClient", (sp, httpClient) =>
134
{
145
var configuration = sp.GetRequiredService<IConfiguration>();
@@ -18,15 +9,17 @@
189
httpClient.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
1910
});
2011

21-
var app = builder.Build();
22-
23-
// Configure the HTTP request pipeline.
24-
25-
app.UseHttpsRedirection();
26-
27-
app.UseAuthorization();
12+
builder.Services.AddHttpClient("ResilientClient", httpClient =>
13+
{
14+
httpClient.BaseAddress = new Uri("http://localhost:5000");
15+
})
16+
.AddStandardResilienceHandler(options =>
17+
{
18+
options.AttemptTimeout.Timeout = TimeSpan.FromSeconds(2);
19+
options.TotalRequestTimeout.Timeout = TimeSpan.FromSeconds(8);
20+
});
2821

29-
app.MapControllers();
22+
var app = builder.Build();
3023

3124
app.MapGet("/api/delay-4-seconds", async (CancellationToken cancellationToken) => await Task.Delay(TimeSpan.FromSeconds(4), cancellationToken));
3225

@@ -36,7 +29,7 @@
3629

3730
try
3831
{
39-
var response = await httpClient.GetAsync("/api/delay-4-seconds");
32+
using var response = await httpClient.GetAsync("/api/delay-4-seconds");
4033

4134
return Results.Ok();
4235
}
@@ -53,7 +46,7 @@
5346

5447
try
5548
{
56-
var response = await httpClient.GetAsync($"/api/delay-4-seconds", cancellationToken);
49+
using var response = await httpClient.GetAsync($"/api/delay-4-seconds", cancellationToken);
5750

5851
return Results.Ok();
5952
}
@@ -71,7 +64,7 @@
7164

7265
try
7366
{
74-
var response = await httpClient.GetAsync("/api/delay-4-seconds", tokenSource.Token);
67+
using var response = await httpClient.GetAsync("/api/delay-4-seconds", tokenSource.Token);
7568

7669
return Results.Ok();
7770
}
@@ -83,4 +76,40 @@
8376
}
8477
});
8578

79+
app.MapGet("/api/test-timeout-vs-cancellation", async (IHttpClientFactory httpClientFactory, CancellationToken cancellationToken) =>
80+
{
81+
var httpClient = httpClientFactory.CreateClient("TestClient");
82+
83+
try
84+
{
85+
using var response = await httpClient.GetAsync("/api/delay-4-seconds", cancellationToken);
86+
87+
return Results.Ok();
88+
}
89+
catch (OperationCanceledException ex) when (ex.InnerException is TimeoutException)
90+
{
91+
return Results.Text("The request timed out");
92+
}
93+
catch (OperationCanceledException)
94+
{
95+
return Results.Text("The caller canceled the request");
96+
}
97+
});
98+
99+
app.MapGet("/api/test-resilience-timeout", async (IHttpClientFactory httpClientFactory) =>
100+
{
101+
var httpClient = httpClientFactory.CreateClient("ResilientClient");
102+
103+
try
104+
{
105+
using var response = await httpClient.GetAsync("/api/delay-4-seconds");
106+
107+
return Results.Ok();
108+
}
109+
catch (Exception ex)
110+
{
111+
return Results.Text($"{ex.GetType().Name} after {httpClient.Timeout}");
112+
}
113+
});
114+
86115
app.Run();

‎aspnetcore-features/HttpClientDefaultAndPerRequestTimeOut/Tests/HttpClientDefaultAndPerRequestTimeOut.Tests/EndpointsLiveTests.cs‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,30 @@ public async Task GivenCustomTokenIsCombinedWithGlobalAndRequestToken_WhenTheReq
5555
// Assert
5656
await Assert.ThrowsAsync<TaskCanceledException>(() => client.GetAsync("/api/test-combined-timeout", cts.Token));
5757
}
58+
59+
[Fact]
60+
public async Task WhenTheTimeoutElapses_ThenTheOperationCanceledExceptionNestsATimeoutException()
61+
{
62+
// Arrange
63+
var client = _factory.CreateClient();
64+
65+
// Act
66+
var responseMessage = await client.GetStringAsync("/api/test-timeout-vs-cancellation");
67+
68+
// Assert
69+
Assert.Equal("The request timed out", responseMessage);
70+
}
71+
72+
[Fact]
73+
public async Task WhenTheResilienceHandlerTimesOut_ThenItThrowsTimeoutRejectedExceptionAndDisablesHttpClientTimeout()
74+
{
75+
// Arrange
76+
var client = _factory.CreateClient();
77+
78+
// Act
79+
var responseMessage = await client.GetStringAsync("/api/test-resilience-timeout");
80+
81+
// Assert
82+
Assert.Equal("TimeoutRejectedException after -00:00:00.0010000", responseMessage);
83+
}
5884
}

‎aspnetcore-features/HttpClientDefaultAndPerRequestTimeOut/Tests/HttpClientDefaultAndPerRequestTimeOut.Tests/HttpClientDefaultAndPerRequestTimeOut.Tests.csproj‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFramework>net10.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77

@@ -10,11 +10,11 @@
1010
</PropertyGroup>
1111

1212
<ItemGroup>
13-
<PackageReference Include="coverlet.collector" Version="6.0.0" />
14-
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.4" />
15-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
16-
<PackageReference Include="xunit" Version="2.5.3" />
17-
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
13+
<PackageReference Include="coverlet.collector" Version="10.0.1" />
14+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.12" />
15+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.1" />
16+
<PackageReference Include="xunit" Version="2.9.3" />
17+
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.0" />
1818
</ItemGroup>
1919

2020
<ItemGroup>

‎collections-csharp/ConcurrentBagInCSharp/ConcurrentBagInCSharp/ConcurrentBagDemo.cs‎

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
using System.Collections.Concurrent;
2-
using System.Collections;
32

43
namespace ConcurrentBagInCSharp
54
{
65
public class ConcurrentBagDemo
76
{
8-
public static ConcurrentBag<int> CreateConcurrentBag()
7+
public static ConcurrentBag<int> CreateEmptyConcurrentBag()
98
{
10-
ConcurrentBag<int> myNumbers = new();
9+
return new ConcurrentBag<int>();
10+
}
1111

12-
var myConcurrentBag = new ConcurrentBag<int>() { 2, 4, 6, 8, 10 };
13-
var myConcurrentBagCount = myConcurrentBag.Count;
12+
public static ConcurrentBag<int> CreateConcurrentBagWithInitialItems()
13+
{
14+
return new ConcurrentBag<int>() { 2, 4, 6, 8, 10 };
15+
}
1416

17+
public static ConcurrentBag<int> CreateConcurrentBag()
18+
{
1519
var myList = new List<int>() { 1, 2, 3, 4, 5, 6, 7 };
16-
var anotherConcurrentBag = new ConcurrentBag<int>(myList);
1720

18-
return anotherConcurrentBag;
21+
return new ConcurrentBag<int>(myList);
1922
}
2023

2124
public static ConcurrentBag<int> CreateAndAddToConcurrentBagConcurrently()
@@ -30,9 +33,9 @@ public static ConcurrentBag<int> CreateAndAddToConcurrentBagConcurrently()
3033
return numbersBag;
3134
}
3235

33-
public static ArrayList RemoveFromConcurrentBag(ConcurrentBag<int> numbersBag)
36+
public static List<int> RemoveFromConcurrentBag(ConcurrentBag<int> numbersBag)
3437
{
35-
var result = new ArrayList();
38+
var result = new List<int>();
3639
if (numbersBag.TryTake(out int number))
3740
{
3841
result.Add(number);
@@ -41,9 +44,9 @@ public static ArrayList RemoveFromConcurrentBag(ConcurrentBag<int> numbersBag)
4144
return result;
4245
}
4346

44-
public static ArrayList RemoveFromConcurrentBagConcurrently(ConcurrentBag<int> bag)
47+
public static List<int> RemoveFromConcurrentBagConcurrently(ConcurrentBag<int> bag)
4548
{
46-
var numbersList = new ArrayList();
49+
var numbersList = new List<int>();
4750
Parallel.For(0, 20, i =>
4851
{
4952
if (bag.TryTake(out int number))
@@ -56,9 +59,9 @@ public static ArrayList RemoveFromConcurrentBagConcurrently(ConcurrentBag<int> b
5659
return numbersList;
5760
}
5861

59-
public static ArrayList AccessItemFromAConcurrentBag(ConcurrentBag<int> bag)
62+
public static List<int> AccessItemFromAConcurrentBag(ConcurrentBag<int> bag)
6063
{
61-
var result = new ArrayList();
64+
var result = new List<int>();
6265

6366
if (bag.TryPeek(out int number))
6467
{
@@ -79,27 +82,76 @@ public static void AccessItemFromAConcurrentBagConcurrently(ConcurrentBag<int> b
7982
});
8083
}
8184

82-
public static int[] ConcurrentBagToArrayMethod(ConcurrentBag<int> bag)
85+
public static List<int> DrainOwnQueue()
8386
{
84-
var myArray = new int[bag.Count];
85-
myArray = bag.ToArray();
87+
var bag = new ConcurrentBag<int>();
88+
for (var i = 1; i <= 5; i++)
89+
{
90+
bag.Add(i);
91+
}
92+
93+
var taken = new List<int>();
94+
while (bag.TryTake(out var item))
95+
{
96+
taken.Add(item);
97+
}
8698

87-
return myArray;
99+
return taken;
100+
}
101+
102+
public static List<int> DrainStolenQueue()
103+
{
104+
var bag = new ConcurrentBag<int>();
105+
var taken = new List<int>();
106+
107+
// Dedicated threads, never Task.Run: the thread pool is free to hand both pieces of
108+
// work to the same thread, and a consumer running on the producer's thread pops its
109+
// own queue last in, first out instead of stealing.
110+
var producer = new Thread(() =>
111+
{
112+
for (var i = 0; i < 5; i++)
113+
{
114+
bag.Add(i);
115+
}
116+
});
117+
producer.Start();
118+
producer.Join();
119+
120+
var consumer = new Thread(() =>
121+
{
122+
while (bag.TryTake(out var item))
123+
{
124+
taken.Add(item);
125+
}
126+
});
127+
consumer.Start();
128+
consumer.Join();
129+
130+
return taken;
131+
}
132+
133+
public static int[] ConcurrentBagToArrayMethod(ConcurrentBag<int> bag)
134+
{
135+
return bag.ToArray();
88136
}
89137

90138
public static int[] ConcurrentBagCopyToMethod(ConcurrentBag<int> bag)
91139
{
140+
// Count and CopyTo are two separate operations. In a multithreaded program another
141+
// thread can add an item between them, and CopyTo then throws ArgumentException
142+
// because the destination is too short. Size the destination from a snapshot,
143+
// or generously, whenever other threads can still write to the bag.
92144
var someArray = new int[bag.Count];
93145
bag.CopyTo(someArray, 0);
94146

95147
return someArray;
96148
}
97-
149+
98150
public static void ConcurrentBagClearMethod(ConcurrentBag<int> bag)
99151
{
100152
bag.Clear();
101153

102154
Console.WriteLine($"My concurrent bag contains {bag.Count} item."); // My concurrent bag contains 0 item.
103155
}
104156
}
105-
}
157+
}

‎collections-csharp/ConcurrentBagInCSharp/ConcurrentBagInCSharp/ConcurrentBagInCSharp.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net7.0</TargetFramework>
5+
<TargetFramework>net10.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
88
</PropertyGroup>
Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
1-
namespace ConcurrentBagInCSharp
2-
{
3-
internal class Program
4-
{
5-
static void Main(string[] args)
6-
{
7-
var myConcurrentBag = ConcurrentBagDemo.CreateAndAddToConcurrentBagConcurrently();
8-
var myConcurrentBagCount = myConcurrentBag.Count;
9-
var isMyConcurrentBagEmpty = myConcurrentBag.IsEmpty;
10-
11-
}
12-
}
13-
}
1+
using ConcurrentBagInCSharp;
2+
3+
var myConcurrentBag = ConcurrentBagDemo.CreateAndAddToConcurrentBagConcurrently();
4+
5+
Console.WriteLine($"Count: {myConcurrentBag.Count}");
6+
Console.WriteLine($"IsEmpty: {myConcurrentBag.IsEmpty}");

0 commit comments

Comments
 (0)