Skip to content

Commit fd2b8cd

Browse files
authored
Fix update cache example. Related to #33589. (#33597)
* Fix update cachine example. Related to #33589. * Move details for signal * Corrected caching bits
1 parent 56ca98b commit fd2b8cd

File tree

3 files changed

+20
-15
lines changed

3 files changed

+20
-15
lines changed

docs/core/extensions/caching.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -217,17 +217,20 @@ In the preceding C# code:
217217

218218
Consumers of this service are free to call `GetPhotosAsync` method, and handle photos accordingly. No `HttpClient` is required as the cache contains the photos.
219219

220+
The asynchronous signal is based on an encapsulated <xref:System.Threading.SemaphoreSlim> instance, within a generic-type constrained singleton. The `CacheSignal<T>` relies on an instance of `SemaphoreSlim`:
221+
222+
:::code source="snippets/caching/memory-worker/CacheSignal.cs":::
223+
224+
In the preceding C# code, the decorator pattern is used to wrap an instance of the `SemaphoreSlim`. Since the `CacheSignal<T>` is registered as a singleton, it can be used across all service lifetimes with any generic type &mdash; in this case, the `Photo`. It is responsible for signaling the seeding of the cache.
225+
220226
The `CacheWorker` is a subclass of <xref:Microsoft.Extensions.Hosting.BackgroundService>:
221227

222228
:::code source="snippets/caching/memory-worker/CacheWorker.cs":::
223229

224-
> [!IMPORTANT]
225-
> You need to `override` <xref:Microsoft.Extensions.Hosting.BackgroundService.StartAsync%2A?displayProperty=nameWithType> and call `await _cacheSignal.WaitAsync()` in order to prevent a race condition between the starting of the `CacheWorker` and a call to `PhotoService.GetPhotosAsync`.
226-
227230
In the preceding C# code:
228231

229-
- The constructor requires an `ILogger`, `HttpClient`, `CacheSignal<Photo>`, and `IMemoryCache`.
230-
- The defines an `_updateInterval` of three hours.
232+
- The constructor requires an `ILogger`, `HttpClient`, and `IMemoryCache`.
233+
- The `_updateInterval` is defined for three hours.
231234
- The `ExecuteAsync` method:
232235
- Loops while the app is running.
233236
- Makes an HTTP request to `"https://jsonplaceholder.typicode.com/photos"`, and maps the response as an array of `Photo` objects.
@@ -236,11 +239,7 @@ In the preceding C# code:
236239
- The call to <xref:System.Threading.Tasks.Task.Delay%2A?displayProperty=nameWithType> is awaited, given the update interval.
237240
- After delaying for three hours, the cache is again updated.
238241

239-
The asynchronous signal is based on an encapsulated <xref:System.Threading.SemaphoreSlim> instance, within a generic-type constrained singleton. The `CacheSignal<T>` relies on an instance of `SemaphoreSlim`:
240-
241-
:::code source="snippets/caching/memory-worker/CacheSignal.cs":::
242-
243-
In the preceding C# code, the decorator pattern is used to wrap an instance of the `SemaphoreSlim`. Since the `CacheSignal<T>` is registered as a singleton, it can be used across all service lifetimes with any generic type &mdash; in this case, the `Photo`. It is responsible for signaling the seeding of the cache.
242+
Consumers in the same process could ask the `IMemoryCache` for the photos, but the `CacheWorker` is responsible for updating the cache.
244243

245244
## Distributed caching
246245

docs/core/extensions/snippets/caching/memory-worker/CacheWorker.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ public sealed class CacheWorker : BackgroundService
1111
private readonly IMemoryCache _cache;
1212
private readonly TimeSpan _updateInterval = TimeSpan.FromHours(3);
1313

14+
private bool _isCacheInitialized = false;
15+
1416
private const string Url = "https://jsonplaceholder.typicode.com/photos";
1517

1618
public CacheWorker(
@@ -52,7 +54,11 @@ await _httpClient.GetFromJsonAsync<Photo[]>(
5254
}
5355
finally
5456
{
55-
_cacheSignal.Release();
57+
if (!_isCacheInitialized)
58+
{
59+
_cacheSignal.Release();
60+
_isCacheInitialized = true;
61+
}
5662
}
5763

5864
try

docs/core/extensions/snippets/caching/memory-worker/Program.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
services.AddScoped<PhotoService>();
1010
services.AddSingleton(typeof(CacheSignal<>));
1111
})
12+
.UseConsoleLifetime()
1213
.Build();
1314

1415
await host.StartAsync();
@@ -26,11 +27,10 @@
2627

2728
PhotoService service =
2829
scope.ServiceProvider.GetRequiredService<PhotoService>();
29-
30-
IAsyncEnumerable<Photo> photos = service.GetPhotosAsync(p => p.AlbumId == id);
31-
await foreach (Photo photo in photos)
30+
31+
await foreach (Photo photo in service.GetPhotosAsync(p => p.AlbumId == id))
3232
{
33-
logger.LogInformation(photo.ToString());
33+
logger.LogInformation("{PhotoDetails}", photo.ToString());
3434
}
3535

3636
logger.LogInformation("");

0 commit comments

Comments
 (0)