2017-02-19 64 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取消加載過程,並在加載過程中定期檢查令牌取消狀態。