Added pooling to locking to reduce memory allocations; ConfigureAwait(false) (#542)
This commit is contained in:
Родитель
15419b3b93
Коммит
fac43d09bd
|
@ -80,7 +80,7 @@ file sealed class TryParseApiNameHandler(ManagementServiceDirectory serviceDirec
|
|||
/// </summary>
|
||||
file sealed class ApiSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<ApiName> locker = new();
|
||||
private readonly AsyncKeyedLocker<ApiName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<ApiName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -89,7 +89,7 @@ file sealed class ApiSemaphore : IDisposable
|
|||
public async ValueTask Run(ApiName name, Func<ApiName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -56,7 +56,7 @@ file sealed class TryParseApiOperationPolicyNameHandler(ManagementServiceDirecto
|
|||
/// </summary>
|
||||
file sealed class ApiOperationPolicySemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<(ApiOperationPolicyName, ApiOperationName, ApiName)> locker = new();
|
||||
private readonly AsyncKeyedLocker<(ApiOperationPolicyName, ApiOperationName, ApiName)> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<(ApiOperationPolicyName, ApiOperationName, ApiName)> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,7 @@ file sealed class ApiOperationPolicySemaphore : IDisposable
|
|||
public async ValueTask Run(ApiOperationPolicyName name, ApiOperationName apiOperationName, ApiName apiName, Func<ApiOperationPolicyName, ApiOperationName, ApiName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync((name, apiOperationName, apiName), cancellationToken);
|
||||
using var _ = await locker.LockAsync((name, apiOperationName, apiName), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains((name, apiOperationName, apiName)))
|
||||
|
|
|
@ -56,7 +56,7 @@ file sealed class TryParseApiPolicyNameHandler(ManagementServiceDirectory servic
|
|||
/// </summary>
|
||||
file sealed class ApiPolicySemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<(ApiPolicyName, ApiName)> locker = new();
|
||||
private readonly AsyncKeyedLocker<(ApiPolicyName, ApiName)> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<(ApiPolicyName, ApiName)> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,7 @@ file sealed class ApiPolicySemaphore : IDisposable
|
|||
public async ValueTask Run(ApiPolicyName name, ApiName apiName, Func<ApiPolicyName, ApiName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync((name, apiName), cancellationToken);
|
||||
using var _ = await locker.LockAsync((name, apiName), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains((name, apiName)))
|
||||
|
|
|
@ -56,7 +56,7 @@ file sealed class TryParseTagNameHandler(ManagementServiceDirectory serviceDirec
|
|||
/// </summary>
|
||||
file sealed class ApiTagSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<(TagName, ApiName)> locker = new();
|
||||
private readonly AsyncKeyedLocker<(TagName, ApiName)> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<(TagName, ApiName)> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,7 @@ file sealed class ApiTagSemaphore : IDisposable
|
|||
public async ValueTask Run(TagName name, ApiName apiName, Func<TagName, ApiName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync((name, apiName), cancellationToken);
|
||||
using var _ = await locker.LockAsync((name, apiName), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains((name, apiName)))
|
||||
|
|
|
@ -82,7 +82,7 @@ file sealed class TryParseBackendNameHandler(ManagementServiceDirectory serviceD
|
|||
/// </summary>
|
||||
file sealed class BackendSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<BackendName> locker = new();
|
||||
private readonly AsyncKeyedLocker<BackendName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<BackendName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -91,7 +91,7 @@ file sealed class BackendSemaphore : IDisposable
|
|||
public async ValueTask Run(BackendName name, Func<BackendName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -61,7 +61,7 @@ file sealed class TryParseDiagnosticNameHandler(ManagementServiceDirectory servi
|
|||
/// </summary>
|
||||
file sealed class DiagnosticSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<DiagnosticName> locker = new();
|
||||
private readonly AsyncKeyedLocker<DiagnosticName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<DiagnosticName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -70,7 +70,7 @@ file sealed class DiagnosticSemaphore : IDisposable
|
|||
public async ValueTask Run(DiagnosticName name, Func<DiagnosticName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -59,7 +59,7 @@ file sealed class TryParseGatewayNameHandler(ManagementServiceDirectory serviceD
|
|||
/// </summary>
|
||||
file sealed class GatewaySemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<GatewayName> locker = new();
|
||||
private readonly AsyncKeyedLocker<GatewayName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<GatewayName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -68,7 +68,7 @@ file sealed class GatewaySemaphore : IDisposable
|
|||
public async ValueTask Run(GatewayName name, Func<GatewayName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -56,7 +56,7 @@ file sealed class TryParseApiNameHandler(ManagementServiceDirectory serviceDirec
|
|||
/// </summary>
|
||||
file sealed class GatewayApiSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<(ApiName, GatewayName)> locker = new();
|
||||
private readonly AsyncKeyedLocker<(ApiName, GatewayName)> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<(ApiName, GatewayName)> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,7 @@ file sealed class GatewayApiSemaphore : IDisposable
|
|||
public async ValueTask Run(ApiName name, GatewayName gatewayName, Func<ApiName, GatewayName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync((name, gatewayName), cancellationToken);
|
||||
using var _ = await locker.LockAsync((name, gatewayName), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains((name, gatewayName)))
|
||||
|
|
|
@ -59,7 +59,7 @@ file sealed class TryParseGroupNameHandler(ManagementServiceDirectory serviceDir
|
|||
/// </summary>
|
||||
file sealed class GroupSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<GroupName> locker = new();
|
||||
private readonly AsyncKeyedLocker<GroupName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<GroupName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -68,7 +68,7 @@ file sealed class GroupSemaphore : IDisposable
|
|||
public async ValueTask Run(GroupName name, Func<GroupName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
using AsyncKeyedLock;
|
||||
|
||||
namespace publisher
|
||||
{
|
||||
internal static class LockOptions
|
||||
{
|
||||
private readonly static AsyncKeyedLockOptions defaultOptions = new()
|
||||
{
|
||||
PoolSize = 20,
|
||||
PoolInitialFill = 1
|
||||
};
|
||||
|
||||
internal static AsyncKeyedLockOptions Default => defaultOptions;
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ file sealed class TryParseLoggerNameHandler(ManagementServiceDirectory serviceDi
|
|||
/// </summary>
|
||||
file sealed class LoggerSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<LoggerName> locker = new();
|
||||
private readonly AsyncKeyedLocker<LoggerName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<LoggerName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -68,7 +68,7 @@ file sealed class LoggerSemaphore : IDisposable
|
|||
public async ValueTask Run(LoggerName name, Func<LoggerName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -104,7 +104,7 @@ file sealed class PutNamedValueHandler(FindNamedValueDto findDto, PutNamedValueI
|
|||
/// </summary>
|
||||
file sealed class NamedValueSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<NamedValueName> locker = new();
|
||||
private readonly AsyncKeyedLocker<NamedValueName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<NamedValueName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -113,7 +113,7 @@ file sealed class NamedValueSemaphore : IDisposable
|
|||
public async ValueTask Run(NamedValueName name, Func<NamedValueName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -92,7 +92,7 @@ file sealed class TryParsePolicyFragmentNameHandler(ManagementServiceDirectory s
|
|||
/// </summary>
|
||||
file sealed class PolicyFragmentSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<PolicyFragmentName> locker = new();
|
||||
private readonly AsyncKeyedLocker<PolicyFragmentName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<PolicyFragmentName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -101,7 +101,7 @@ file sealed class PolicyFragmentSemaphore : IDisposable
|
|||
public async ValueTask Run(PolicyFragmentName name, Func<PolicyFragmentName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -60,7 +60,7 @@ file sealed class TryParseProductNameHandler(ManagementServiceDirectory serviceD
|
|||
/// </summary>
|
||||
file sealed class ProductSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<ProductName> locker = new();
|
||||
private readonly AsyncKeyedLocker<ProductName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<ProductName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -69,7 +69,7 @@ file sealed class ProductSemaphore : IDisposable
|
|||
public async ValueTask Run(ProductName name, Func<ProductName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -56,7 +56,7 @@ file sealed class TryParseApiNameHandler(ManagementServiceDirectory serviceDirec
|
|||
/// </summary>
|
||||
file sealed class ProductApiSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<(ApiName, ProductName)> locker = new();
|
||||
private readonly AsyncKeyedLocker<(ApiName, ProductName)> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<(ApiName, ProductName)> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,7 @@ file sealed class ProductApiSemaphore : IDisposable
|
|||
public async ValueTask Run(ApiName name, ProductName productName, Func<ApiName, ProductName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync((name, productName), cancellationToken);
|
||||
using var _ = await locker.LockAsync((name, productName), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains((name, productName)))
|
||||
|
|
|
@ -56,7 +56,7 @@ file sealed class TryParseGroupNameHandler(ManagementServiceDirectory serviceDir
|
|||
/// </summary>
|
||||
file sealed class ProductGroupSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<(GroupName, ProductName)> locker = new();
|
||||
private readonly AsyncKeyedLocker<(GroupName, ProductName)> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<(GroupName, ProductName)> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,7 @@ file sealed class ProductGroupSemaphore : IDisposable
|
|||
public async ValueTask Run(GroupName name, ProductName productName, Func<GroupName, ProductName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync((name, productName), cancellationToken);
|
||||
using var _ = await locker.LockAsync((name, productName), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains((name, productName)))
|
||||
|
|
|
@ -56,7 +56,7 @@ file sealed class TryParseProductPolicyNameHandler(ManagementServiceDirectory se
|
|||
/// </summary>
|
||||
file sealed class ProductPolicySemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<(ProductPolicyName, ProductName)> locker = new();
|
||||
private readonly AsyncKeyedLocker<(ProductPolicyName, ProductName)> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<(ProductPolicyName, ProductName)> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,7 @@ file sealed class ProductPolicySemaphore : IDisposable
|
|||
public async ValueTask Run(ProductPolicyName name, ProductName productName, Func<ProductPolicyName, ProductName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync((name, productName), cancellationToken);
|
||||
using var _ = await locker.LockAsync((name, productName), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains((name, productName)))
|
||||
|
|
|
@ -56,7 +56,7 @@ file sealed class TryParseTagNameHandler(ManagementServiceDirectory serviceDirec
|
|||
/// </summary>
|
||||
file sealed class ProductTagSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<(TagName, ProductName)> locker = new();
|
||||
private readonly AsyncKeyedLocker<(TagName, ProductName)> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<(TagName, ProductName)> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,7 @@ file sealed class ProductTagSemaphore : IDisposable
|
|||
public async ValueTask Run(TagName name, ProductName productName, Func<TagName, ProductName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync((name, productName), cancellationToken);
|
||||
using var _ = await locker.LockAsync((name, productName), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains((name, productName)))
|
||||
|
|
|
@ -56,7 +56,7 @@ file sealed class TryParseServicePolicyNameHandler(ManagementServiceDirectory se
|
|||
/// </summary>
|
||||
file sealed class ServicePolicySemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<ServicePolicyName> locker = new();
|
||||
private readonly AsyncKeyedLocker<ServicePolicyName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<ServicePolicyName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,7 @@ file sealed class ServicePolicySemaphore : IDisposable
|
|||
public async ValueTask Run(ServicePolicyName name, Func<ServicePolicyName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -61,7 +61,7 @@ file sealed class TryParseSubscriptionNameHandler(ManagementServiceDirectory ser
|
|||
/// </summary>
|
||||
file sealed class SubscriptionSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<SubscriptionName> locker = new();
|
||||
private readonly AsyncKeyedLocker<SubscriptionName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<SubscriptionName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -70,7 +70,7 @@ file sealed class SubscriptionSemaphore : IDisposable
|
|||
public async ValueTask Run(SubscriptionName name, Func<SubscriptionName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -59,7 +59,7 @@ file sealed class TryParseTagNameHandler(ManagementServiceDirectory serviceDirec
|
|||
/// </summary>
|
||||
file sealed class TagSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<TagName> locker = new();
|
||||
private readonly AsyncKeyedLocker<TagName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<TagName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -68,7 +68,7 @@ file sealed class TagSemaphore : IDisposable
|
|||
public async ValueTask Run(TagName name, Func<TagName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
|
@ -59,7 +59,7 @@ file sealed class TryParseVersionSetNameHandler(ManagementServiceDirectory servi
|
|||
/// </summary>
|
||||
file sealed class VersionSetSemaphore : IDisposable
|
||||
{
|
||||
private readonly AsyncKeyedLocker<VersionSetName> locker = new();
|
||||
private readonly AsyncKeyedLocker<VersionSetName> locker = new(LockOptions.Default);
|
||||
private ImmutableHashSet<VersionSetName> processedNames = [];
|
||||
|
||||
/// <summary>
|
||||
|
@ -68,7 +68,7 @@ file sealed class VersionSetSemaphore : IDisposable
|
|||
public async ValueTask Run(VersionSetName name, Func<VersionSetName, CancellationToken, ValueTask> action, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do not process the same name simultaneously
|
||||
using var _ = await locker.LockAsync(name, cancellationToken);
|
||||
using var _ = await locker.LockAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Only process each name once
|
||||
if (processedNames.Contains(name))
|
||||
|
|
Загрузка…
Ссылка в новой задаче