AsyncCache 3.0.4
dotnet add package AsyncCache --version 3.0.4
NuGet\Install-Package AsyncCache -Version 3.0.4
<PackageReference Include="AsyncCache" Version="3.0.4" />
paket add AsyncCache --version 3.0.4
#r "nuget: AsyncCache, 3.0.4"
// Install AsyncCache as a Cake Addin #addin nuget:?package=AsyncCache&version=3.0.4 // Install AsyncCache as a Cake Tool #tool nuget:?package=AsyncCache&version=3.0.4
AsyncCache
Async cache uses an "async lock" (a semaphore) to prevent competing/simultaneous calls to the data source.
Usage
AsyncCache is not a singleton. If you want your cached key/values to be scoped as a singleton (also just generally speaking), I recommend using a dependency injector to instantiate AsyncCache.
The reason the cached key/values are scoped to the instance of AsyncCache is this way you can control both the TimeSpan and the scope of your key/values.
Usage Example Note: Don't use .Result from a task. Async functions should be called by async functions. This is just an example app to illustrate usage of AsyncCache. This example app is synchronous..so maybe a bad example but it should still illistrate the usage.
using Cache;
using System;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var random = new Random();
var cache = new AsyncCache();
Console.WriteLine("Not Cached:");
for (var i = 0; i < 5; i++)
Console.WriteLine(random.Next(0, 5));
Console.WriteLine("\nCached:");
for (var i = 0; i < 5; i++)
Console.WriteLine(cache.Get(
key: "random integer",
dataSource: () => Task.FromResult(random.Next(0, 5))).Result);
Console.ReadKey();
}
}
}
Example App Output:
Not Cached:
4
2
2
4
0
Cached:
2
2
2
2
2
Here is example usage from unit tests (below). Did I mention how simple it is?
[TestInitialize]
public void Setup()
{
_cache = new AsyncCache();
}
[TestMethod]
public async Task ShouldReturnResultFromDataSourceTask()
{
//Arrange
//Act
int result = await _cache.Get("some key", () => Task.FromResult(2));
//Assert
result.Should().Be(2);
}
[TestMethod]
public async Task ShouldLockToPreventRaceCondition()
{
var tcs1 = new TaskCompletionSource<int>();
var tcs2 = new TaskCompletionSource<int>();
int? result1 = null;
int? result2 = null;
var get1 = _cache.Get(key: "key1", dataSource: () => tcs1.Task).ContinueWith(t => result1 = t.Result);
var get2 = _cache.Get(key: "key1", dataSource: () => tcs2.Task).ContinueWith(t => result2 = t.Result);
tcs1.SetResult(1);
tcs2.SetResult(2);
await Task.WhenAll(get1, get2);
result1.Should().Be(1, "because this is the initial value inserted into the cache.");
result2.Should().Be(1, "because the previous/parallel request should've already inserted 1");
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. |
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
3.0.4 | 81 | 12/5/2024 |
3.0.3 | 2,137 | 1/31/2024 |
3.0.2 | 473 | 11/28/2023 |
2.0.1 | 1,758 | 9/30/2021 |
1.0.67 | 402 | 9/30/2021 |
1.0.66 | 346 | 9/30/2021 |
1.0.65 | 489 | 9/25/2021 |
1.0.64 | 382 | 9/24/2021 |
1.0.39 | 5,712 | 7/1/2018 |
1.0.38 | 1,078 | 3/14/2018 |
1.0.37 | 1,312 | 10/11/2017 |
1.0.34 | 1,085 | 3/16/2017 |
1.0.33 | 1,406 | 11/16/2016 |
1.0.32 | 1,286 | 11/16/2016 |
1.0.31 | 1,232 | 11/16/2016 |
1.0.30 | 1,668 | 6/16/2016 |
1.0.28 | 1,204 | 3/19/2016 |
1.0.27 | 1,277 | 3/5/2016 |
1.0.26 | 1,297 | 3/5/2016 |
1.0.25 | 1,292 | 2/20/2016 |
1.0.24 | 1,339 | 2/20/2016 |
1.0.23 | 1,312 | 2/20/2016 |
1.0.22 | 1,310 | 2/20/2016 |
1.0.21 | 1,278 | 2/16/2016 |
1.0.20 | 1,319 | 2/16/2016 |
1.0.19 | 1,324 | 2/16/2016 |
1.0.18 | 1,313 | 2/14/2016 |
1.0.1 | 1,323 | 2/14/2016 |
1.0.0 | 12,719 | 2/13/2016 |