2017-02-19 1 views
0

Cela peut être simple, mais n'a pas encore réussi à le comprendre.Annuler le verrouillage sur un objet

En termes simples:

J'ai une longue opération de fonctionnement (environ 8 min) dans ma couche repo.

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; 
    } 
} 

une couche de service appelle la charge de manière asynchrone

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)); 
} 

enfin, ce service est appelé par un point de terminaison API

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

comment je peux venir sur l'annulation de la lock(s_cacheLock) intérieur opération de chargement (premier bloc de code) lorsque la condition suivante est vraie

//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) 
} 

de sorte qu'un autre thread n'aura pas à attendre jusqu'à ce que la charge précédente a été achevée?

Remarque: J'ai besoin du lock(m_cacheLock) parce que j'ai d'autres méthodes qui lisent des caches et ne devraient vraiment pas le faire jusqu'à ce que tous les caches soient chargés.

+3

Chargez-le dans une tâche et utilisez un jeton d'annulation pour annuler la tâche précédente. Cela devrait arrêter la tâche dans ~ 20 ms et ainsi sortir de l'instruction lock. –

+1

Vous ne pouvez pas "libérer" 'lock'. Vous pouvez envisager d'utiliser d'autres constructions de synchronisation. –

+0

@ThomasWeller: Je ne semble pas comprendre tout le changement de mon code dans mon esprit, cela vous dérangerait-il de donner un exemple sur la façon dont le passage d'un canceltoken annulerait la tâche précédente? –

Répondre

-1

Utilisez Monitor.Enter & Monitor.Exit à la place du verrou, veillez à intercepter les exceptions et à libérer le verrou.

Exemple:

Monitor.Enter(s_cacheLock) 

// do work 

Monitor.Exit(s_cacheLock) 
+3

comment utiliser moniteur est différent de l'utilisation de verrouillage dans mon cas. et comment cela me donne le contrôle sur le mécanisme de verrouillage? –

+0

@RamiShareef, Vous avez demandé d'annuler le verrou si une certaine condition est remplie, dans ce cas vous pouvez simplement utiliser Monitor.Exit pour "annuler" le verrou sur s_cacheLock – Keddy1201

0

Il n'y a pas besoin d'utiliser le verrouillage pour protéger le processus de charge de 8 minutes, ce que vous avez besoin est juste verrouiller l'instruction set cache de mise à jour après la charge complète. Vous devez également rendre le processus de chargement annulable à l'aide d'un CancellationToken et vérifier périodiquement l'état d'annulation du jeton pendant le processus de chargement.