2010-06-25 8 views
1

J'ai un problème concernant le multithreading et l'insertion d'un élément dans un dictionnaire. La situation suivante est ce que je suis encoutering lorsque les sujets insertingen avec Dupliquons d'id:Conflit sur Verrouillage de deux méthodes pour qu'un seul thread puisse utiliser le verrou

private static readonly Timer bufferChecker; 
    private static readonly List<SubjectStartRulePair> inBuffer; 
    private static readonly IDictionary<Guid, Subject> beingProcessed; 
    private static readonly object objLock; 

    static InBuffer() 
    { 
     objLock = new object(); 
     inBuffer = new List<SubjectStartRulePair>(); 
     beingProcessed = new Dictionary<Guid, Subject>(); 
     bufferChecker = new Timer(x => ProcessThreads(), null, 1000, 1000); 
    } 

    public static void ProcessThreads() 
    { 
     lock(objLock) 
     { 
      var bufferedItems = inBuffer.OrderBy(x => x.QueuedTime); 
      foreach (var item in bufferedItems) 
      { 
       if (!beingProcessed.ContainsKey(item.Subject.SubjectId)) //Important check which validates if there is already a Thread running 
       { 
        var thread = new Thread(
         x => 
         { 
          //Thread #2 is here and runs into duplicate Key 
          beingProcessed.Add(item.Subject.SubjectId, item.Subject); 
          item.StartRule(item.Subject); 
          beingProcessed.Remove(item.Subject.SubjectId); 
         }); 

        thread.Start(); 
        inBuffer.Remove(item); 
       } 
      } 
     } 
    } 

    public static void TryToExecute(Subject subject, IBusinessRule rule) 
    { 
     lock (objLock) 
     { 
      if (beingProcessed.ContainsKey(subject.SubjectId)) //Important check which validates if there is already a Thread running 
      { 
       inBuffer.Add(
        new SubjectStartRulePair 
         { 
          QueuedTime = DateTime.Now, 
          Subject = subject, 
          StartRule = (x => 
          { 
           rule.RunChildren(subject); 
           return true; 
          }) 
         } 
       ); 
      } 
      else 
      { 
       var thread = new Thread(
        x => 
        { 
         beingProcessed.Add(subject.SubjectId, subject); 
         rule.RunChildren(subject); 
         beingProcessed.Remove(subject.SubjectId); 
        }); 

       thread.Start(); //Thread #1 is here 
      } 
     } 
    } 

j'ai bloqué les deux méthodes, mais la serrure ne semble pas fonctionner ... Il semble que deux threads à la fois entrer dans la serrure les différentes méthodes. Ai-je manqué le point d'utiliser lock()? Une idée sur la façon dont je devrais mettre en œuvre correctement? Important sidenote, la méthode ProcessThreads() est appelée chaque seconde par un Timer (bufferChecker).

Répondre

2

Vous démarrez un nouveau thread dans chaque méthode - ces nouveaux threads n'auront pas (ou ne demanderont pas) le verrou.

Ainsi, bien qu'un seul de ProcessThreads ou TryToExecute puisse effectivement fonctionner à la fois, vous n'avez aucun contrôle sur les bits dans les expressions lambda. Si ceux-ci nécessitent également une exclusion mutuelle, vous devez mettre une déclaration lock dans ces lambdas.

+0

Merci pour la rapidité de la réponse Jon! J'ai déplacé le beingProcessed.Add() en dehors du lambda pour résoudre ce problème, ce qui donne aussi le résultat désiré:] – Bas