2017-02-19 74 views
0

这可能很简单,但还不知道。取消锁定对象

简单地说:

我在回购层有一个长期运行的操作(约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; 
    } 
} 

服务层调用加载异步

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),因为我有其他方法可以读取缓存,并且在所有缓存加载之前都不应该这样做。

+3

将其加载到任务中,并使用取消令牌取消先前的任务。这应该在〜20 ms内停止任务,从而跳出锁定语句。 –

+1

你不能“释放”锁定。您可以考虑使用其他同步结构。 –

+0

@ThomasWeller:我似乎无法理解我脑海中对代码的全部改变,您是否介意给出一个关于如何通过canceltoken来取消上一个任务的示例? –

回答

-1

使用Monitor.Enter & Monitor.Exit而不是锁,确保捕获异常并释放锁。

例子:

Monitor.Enter(s_cacheLock) 

// do work 

Monitor.Exit(s_cacheLock) 
+3

如何在我的情况下使用监视器与使用锁定不同。以及如何让我控制锁定机制? –

+0

@RamiShareef,如果满足某个条件,您已经要求取消锁定,在这种情况下,您可以使用Monitor.Exit来“取消”s_cacheLock上的锁定 – Keddy1201

0

无需使用锁来保护8分钟加载过程,你需要的只是锁定更新缓存加载完成后,SET语句。您还应该使用CancellationToken取消加载过程,并在加载过程中定期检查令牌取消状态。