c# - 在单独的线程中同步更新属性
问题描述
我有一个继承自BackgroundService
. 它在应用程序的整个生命周期内运行一个任务,在该任务中,我有一个循环进行一些计算,其中一些使用可设置的属性,这些属性可以从另一个线程设置。对于循环的一次迭代,我必须确保这些属性都不会改变,所以我的所有计算都使用相同的值。
我最初处理这个问题的方法是让我的 require 属性实际上只是将一个动作放在队列中,然后在我的循环开始时执行这些动作。所以,我最终得到了这样的结果:
private MyConfig Config { get; set; }
private readonly ConcurrentQueue<Action> queue = new ConcurrentQueue<Action>();
public void UpdateConfig(MyConfig config)
{
queue.Enqueue(() => Config = config);
}
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Run(async () =>
{
while (!stoppingToken.IsCancellationRequested)
{
for (int i = queue.Count; i > 0; i--)
{
queue.TryDequeue(out Action element);
element?.Invoke();
}
}
//now do some stuff with the updated config and maybe other properties too
});
}
我觉得可能有更好的方法。我应该锁定这些属性吗?在这一点上,我不确定最好的解决方案。
解决方案
以下是我认为的标准模式:使用lock
对象同步对共享字段的访问。
private readonly object _locker = new object();
private MyConfig _config;
public void UpdateConfig(MyConfig config)
{
lock (_locker) _config = config;
}
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Run(async () =>
{
while (!stoppingToken.IsCancellationRequested)
{
MyConfig localConfig; lock (_locker) localConfig = _config;
// Do stuff with the localConfig. Don't use the shared _config field.
}
});
}
MyConfig
如果类型是不可变的,这应该是线程安全的。它应该同样适用于class
or 或struct
MyConfig
。
推荐阅读
- sql - 如何在分组后组合值为varchar的列
- angular - Angular 4在http post请求后获取函数返回值
- php - 从模型 laravel 访问关系
- java - 如果excel中的单元格值为null,我尝试通过在java中使用if语句来分配一个值
- yii2 - 通过 Yii2 中的自定义控制器为特定用户启用调试器工具
- javascript - 获取“堂兄弟”的属性
- c# - C# 将带有字符串的结构编组到 C 库
- undefined - GNU Octave:“形状”未定义,即使它被定义为函数参数
- javascript - 从 C# 变量中获取数据表属性的值
- javascript - 如何添加视频元素并使其在启用声音的情况下自动播放