在方法覆盖中访问字典项
Access Dictionary Items within Method Override
我在添加到字典的 webapi 中有以下 class,但是每次触发 checkstatus 方法(使用 Task.Delay)时,它都说字典是空的。这是因为它的 运行 在不同的线程上吗?我应该改用并发词典吗?
internal class Sms : smsBase
{
private const int CheckFrequencyMilliseconds = 1000;
private Dictionary<CustomerDetails, decimal> _registeredCustomers;
public Sms(ILogger<Sms> logger)
: base(TimeSpan.FromMilliseconds(CheckFrequencyMilliseconds), logger)
{
_registeredCustomers = new Dictionary<CustomerDetails, decimal>();
}
protected override Task CheckStatus()
{
foreach (var rc in _registeredCustomers)
{
//do something
}
return Task.CompletedTask;
}
public Task RegisterCustomer(CustomerDetails customer)
{
_registeredCustomers.Add(customer, 1);
return Task.CompletedTask;
}
}
基本 class 代码如下。
public abstract class smsBase : BackgroundService
{
private readonly TimeSpan _tickFrequency;
private readonly ILogger<smsBase> _logger;
/// <inheritdoc />
/// <param name="tickFrequency">Frequency that the service will execute the CheckStatus method.</param>
protected smsBase (TimeSpan tickFrequency,ILogger<smsBase> logger)
{
this._tickFrequency = tickFrequency;
this._logger = logger;
}
/// <inheritdoc />
protected override sealed async Task ExecuteAsync(CancellationToken stoppingToken)
{
this._logger.LogInformation("Service is starting.");
while (!stoppingToken.IsCancellationRequested)
{
ConfiguredTaskAwaitable configuredTaskAwaitable;
try
{
configuredTaskAwaitable = this.CheckStatus().ConfigureAwait(false);
await configuredTaskAwaitable;
}
catch (Exception ex)
{
this._logger.LogError(ex, "An exception was thrown whilst checking registered strategies.");
throw;
}
configuredTaskAwaitable = Task.Delay(this._tickFrequency, stoppingToken).ConfigureAwait(false);
await configuredTaskAwaitable;
}
this._logger.LogInformation("Service is stopping.");
protected abstract Task CheckStatus();
}
下面是启动cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddSwaggerGen(options => {
options.SwaggerDoc("v1", new Info() { Title = "Customers.WebApi", Version = "v1" });
})
.AddMvc(options => {
options.Filters.Add(new ExceptionFilter());
options.Filters.Add(new ProducesAttribute("application/json"));
})
.AddJsonOptions(options => {
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
services.AddHostedService<Sms>();
services.AddSingleton<ISms, Sms>();
}
你的问题漏掉了很多点,但我相信我可以从这两行中得出问题
services.AddHostedService<Sms>();
services.AddSingleton<ISms, Sms>();
AddSingleton
行将为您的应用程序创建 Sms
的单个实例,我怀疑您正在将 ISms
注入某处的控制器并调用 RegisterCustomer
.
AddHostedService
行将创建一个 second Sms 实例,并将其用作托管服务。
解决方案是将这两个东西分开,并有类似 ICustomerRepository
的东西,它由托管服务和控制器共享。
请注意,如果我在这里说得不对,用 ISms
的详细信息编辑您的问题会有所帮助,包括它的使用方式以及您在哪里调用 RegisterCustomer
。
我在添加到字典的 webapi 中有以下 class,但是每次触发 checkstatus 方法(使用 Task.Delay)时,它都说字典是空的。这是因为它的 运行 在不同的线程上吗?我应该改用并发词典吗?
internal class Sms : smsBase
{
private const int CheckFrequencyMilliseconds = 1000;
private Dictionary<CustomerDetails, decimal> _registeredCustomers;
public Sms(ILogger<Sms> logger)
: base(TimeSpan.FromMilliseconds(CheckFrequencyMilliseconds), logger)
{
_registeredCustomers = new Dictionary<CustomerDetails, decimal>();
}
protected override Task CheckStatus()
{
foreach (var rc in _registeredCustomers)
{
//do something
}
return Task.CompletedTask;
}
public Task RegisterCustomer(CustomerDetails customer)
{
_registeredCustomers.Add(customer, 1);
return Task.CompletedTask;
}
}
基本 class 代码如下。
public abstract class smsBase : BackgroundService
{
private readonly TimeSpan _tickFrequency;
private readonly ILogger<smsBase> _logger;
/// <inheritdoc />
/// <param name="tickFrequency">Frequency that the service will execute the CheckStatus method.</param>
protected smsBase (TimeSpan tickFrequency,ILogger<smsBase> logger)
{
this._tickFrequency = tickFrequency;
this._logger = logger;
}
/// <inheritdoc />
protected override sealed async Task ExecuteAsync(CancellationToken stoppingToken)
{
this._logger.LogInformation("Service is starting.");
while (!stoppingToken.IsCancellationRequested)
{
ConfiguredTaskAwaitable configuredTaskAwaitable;
try
{
configuredTaskAwaitable = this.CheckStatus().ConfigureAwait(false);
await configuredTaskAwaitable;
}
catch (Exception ex)
{
this._logger.LogError(ex, "An exception was thrown whilst checking registered strategies.");
throw;
}
configuredTaskAwaitable = Task.Delay(this._tickFrequency, stoppingToken).ConfigureAwait(false);
await configuredTaskAwaitable;
}
this._logger.LogInformation("Service is stopping.");
protected abstract Task CheckStatus();
}
下面是启动cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddSwaggerGen(options => {
options.SwaggerDoc("v1", new Info() { Title = "Customers.WebApi", Version = "v1" });
})
.AddMvc(options => {
options.Filters.Add(new ExceptionFilter());
options.Filters.Add(new ProducesAttribute("application/json"));
})
.AddJsonOptions(options => {
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
services.AddHostedService<Sms>();
services.AddSingleton<ISms, Sms>();
}
你的问题漏掉了很多点,但我相信我可以从这两行中得出问题
services.AddHostedService<Sms>();
services.AddSingleton<ISms, Sms>();
AddSingleton
行将为您的应用程序创建 Sms
的单个实例,我怀疑您正在将 ISms
注入某处的控制器并调用 RegisterCustomer
.
AddHostedService
行将创建一个 second Sms 实例,并将其用作托管服务。
解决方案是将这两个东西分开,并有类似 ICustomerRepository
的东西,它由托管服务和控制器共享。
请注意,如果我在这里说得不对,用 ISms
的详细信息编辑您的问题会有所帮助,包括它的使用方式以及您在哪里调用 RegisterCustomer
。