【问题标题】:Cancel lock on an object取消锁定对象
【发布时间】:2017-02-19 19:24:12
【问题描述】:

这可能很简单,但还无法弄清楚。

简单地说:

我的 repo 层中有一个长时间运行的操作(大约 8 分钟)。

public static ReleaseSelection LoadedReleaseSelection = new ReleaseSelection();
private static object s_cacheLock = new object();

public Long Load(ReleaseSelection releaseSelection)
{
    //check if the release passed in to load is different the one previously loaded
    if (releaseSelection != LoadedReleaseSelection)
    {
        //do something to break the lock(s_cacheLock)
    }

    lock (s_cacheLock)
    {
        //Reads from TAB files and put them into cache objects.. runs for about 8 mins

        LoadedReleaseSelection = releaseSelection;
    }
}

服务层异步调用Load

 public Task<long> LoadAsync()
{
    ReleaseSelection releaseSelection = //get value from db through another repo call

    if (releaseSelection == null)
    {
        return null;
    }

    return Task.Factory.StartNew(() => m_releaseRepository.Load(releaseSelection));
} 

最后,这个服务被一个 API 端点调用

public async Task<IHttpActionResult> ReleaseLoadPost()
{
    await m_releaseService.LoadAsync();
    return Ok();
}

当以下条件为真时,我如何才能取消 lock(s_cacheLock) 内部加载操作(第一个代码块)

//check if the release passed in to load is different the one previously loaded
if (releaseSelection != LoadedReleaseSelection)
{
    //do something to break the lock(s_cacheLock)
}

这样另一个线程就不必等到之前的加载完成了吗?

注意:我需要lock(m_cacheLock),因为我有其他从缓存中读取的方法,并且在加载所有缓存之前真的不应该这样做。

【问题讨论】:

  • 将其加载到一个任务中,并使用取消令牌取消上一个任务。这应该会在约 20 毫秒内停止任务,从而跳出锁定语句。
  • 你不能“释放”lock。您可以考虑使用其他同步结构。
  • @ThomasWeller:我似乎不明白我的代码的全部变化,你介意举个例子说明传递取消令牌将如何取消之前的任务吗?
  • @RamiShareef:您的存储库 instances 是否真的在 ASP.NET 调用之间共享?这很不寻常。
  • @StephenCleary 他们不是,在每次调用时我都会得到一个新实例(感谢 IoC)但是,我几乎没有定义为静态的成员来保存有关缓存的信息

标签: c# multithreading locking cancellation


【解决方案1】:

不需要使用lock来保护8分钟的加载过程,只需在加载完成后锁定update cache set语句即可。您还应该使用CancellationToken 取消加载过程,并在加载过程中定期检查令牌取消状态。

【讨论】:

    【解决方案2】:

    使用 Monitor.Enter & Monitor.Exit 代替锁,确保捕获异常并释放锁。

    例子:

    Monitor.Enter(s_cacheLock)
    
    // do work
    
    Monitor.Exit(s_cacheLock)
    

    【讨论】:

    • 在我的情况下,使用监视器与使用锁定有何不同。以及如何让我控制锁定机制?
    • @RamiShareef,如果满足某个条件,您已要求取消锁定,在这种情况下,您可以使用 Monitor.Exit 来“取消”s_cacheLock 上的锁定
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多