【问题标题】:Why my other thread still able to access before SemaphoreSlim released?为什么我的其他线程在 SemaphoreSlim 发布之前仍然可以访问?
【发布时间】:2020-07-16 08:59:47
【问题描述】:

我有一个分钟计划任务,我只想一次访问一个线程,我使用 SemaphoreSlim 作为下面的 C# 代码,但其他线程可以在前一个线程完全完成之前进入.. 我错过了什么?

public static async Task<bool> Update_ThumbnailsAsync(long _survey_pid, bool _thumbnails)
{
    using (var _sem = new SemaphoreSlim(1, 1))
    {
        await _sem.WaitAsync();

        ... doing loop process here
        ...
        ...
        ...
     }
 }

【问题讨论】:

  • 您将SemaphoreSlim 保留在本地范围内。这需要在全球范围内发挥作用。
  • 你为什么在任务中使用信号量?任务是不是线程。你想做什么?有更好的方法来实现这一点,不管它是什么。如果您想控制一次可以有多少工作人员完成一项工作,您可以使用 ActionBlock&lt;T&gt; 或具有单个消费者的 Channel
  • @PanagiotisKanavos 我经常发现自己需要单线程异步代码中的 SemaphoreSlim。原因是async 方法即使在单个线程上也可以重入:虽然线程只能同时执行方法中的一行代码,但方法的多个部分可以立即执行(尽管全部或除一部分之外的全部将卡在awaits 上)。有时一个方法会做[更新状态,等待,更新状态],你需要确保没有其他东西调用同一个方法并在等待期间修改该状态
  • @PanagiotisKanavos,任务和SemaphoreSlim 有什么问题?您可以添加参考以阅读有关此主题的更多信息吗?我没有使用数据流,也没有计划很快开始使用它。

标签: c#


【解决方案1】:

您在函数内声明和实例化信号量,随后对该函数的调用将实例化它们自己的信号量。 您需要将信号量移到函数范围之外。

类似这样的:

private static _sem = new SemaphoreSlim(1, 1);
public static async Task<bool> Update_ThumbnailsAsync(long _survey_pid, bool _thumbnails)
{   
    await _sem.WaitAsync();

    ... doing loop process here
    ...
    ...
    ...
 }

【讨论】:

  • 您忘记了static 和可选的:readonly 和处置IDisposable
  • 如果我有 3 个方法,那么我是否需要 _sem1、_sem2 和 _sem3 来控制每个异步方法?
  • @DevDon 是的,这意味着每个方法的“循环过程”一次只能执行一个线程。
  • @Sinatr 如果它是静态的,并且是只读的,则不需要处理它。它要么是只读的,要么是在被新的信号量替换时处置 IDisposable
  • @Lev,可以调用readonly字段中包含的实例方法,包括Dispose()方法。 SemaphoreSlim 必须是 disposed。我的“可选” 表示您不必在答案中添加处置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
  • 2011-05-23
  • 2010-10-08
  • 2013-04-12
相关资源
最近更新 更多