2009-01-13 7 views
0

J'ai un tas d'entités DB chargées dans des objets DB. La même entité de base de données peut être chargée dans plus d'un objet DB. Périodiquement, une entité DB nécessitera un traitement spécial. Ce traitement doit être effectué par un thread à la fois. Le verrouillage est en ordre ici.Objets de simultanéité, de verrouillage et de dictionnaire C#

EDIT: Remarque importante: le processus appelle un service Web lent. C'est ce que j'essaie d'empêcher la concurrence. Je ne vois pas comment cela peut se faire en toute sécurité sans verrous. Je crée donc un objet "cadenas" qui sera référencé par les objets DB pour le verrouillage. L'objet cadenas est basé sur l'entité de sorte que deux ou plusieurs objets DB pour la même entité utilisent le même objet cadenas. Je stocke ces cadenas dans un objet dictionnaire en utilisant l'ID de l'entité DB comme clé. L'objet cadenas est également un simple objet chaîne. Est-ce la bonne approche? Je pense que je suis soit sur l'ingénierie ou la simplification. Si l'approche est correcte, à quoi ressemble ce code? Cela fonctionne, mais je n'ai pas encore testé sous charge.

Merci de

public static func(CustomObject o) 
{ 
    if (ReadyForUpdate(o)) 
    { 
     lock (LookupPadLockByID(object.ID) 
     { 
      if (ReadyForUpdate(o)) 
      { 
       PerformUpdate(object); 
      } 
     } 
    } 
} 

private static readonly object padlockLock = new object(); 
private static readonly Dictionary<int, string> padLocks = new Dictionary<int,string>(); 
private static object LookupPadLockByID(int uniqueID) 
{ 
    lock (padlockLock) 
    { 
     if (!padLocks.ContainsKey(uniqueID)) 
     { 
      padLocks.Add(uniqueID, uniqueID + " is locked"); 
     } 
    } 

    return padLocks[uniqueID]; 
} 
+0

La méthode PeformUpdate appelle un service Web très lent, puis effectue une mise à jour de base de données.C'est ce dont j'ai besoin pour empêcher la concurrence. –

Répondre

1

Eh bien, vous finissez par verrouillage sur une corde, ce qui est une bonne idée (bien que l'ensemble signifie que internait ne devrait pas être un gros problème). Ce qui est un plus gros problème est que:

  • Vous ne semblez pas retirer les verrous de padLocks - est-ce un problème? Vous accédez au dictionnaire en dehors du padlockLock; le return doit être à l'intérieur du lock

Pour ce deuxième, ce serait plus simple:

object itemLock; 
if (!padLocks.TryGetValue(uniqueID, out itemLock)) { 
    itemLock = new object(); 
    padLocks.Add(uniqueID, itemLock); 
} 
return itemLock; 

Si ce code est assez locale (vos objets ont pas encore échappé), vous pourriez tout simplement lock le disque lui-même? Beaucoup plus simple ...

+0

J'ai besoin de regarder dans cette chaîne d'internement. Vous n'êtes pas le seul à le signaler. –

0

Je pense que vous êtes sur l'ingénierie. Si vous avez seulement besoin de protéger vos entités DB (que je suppose est représenté par "objet" dans votre code, que je vais changer en "entité"), vous pouvez simplement l'utiliser comme votre verrou. Tout objet de référence peut être utilisé comme une serrure:

public static func(CustomObject o) 
{ 
    if (ReadyForUpdate(o)) 
    { 
     lock (entity) 
     { 
       if (ReadyForUpdate(o)) 
       { 
         PerformUpdate(entity); 
       } 
     } 
    } 
} 
+0

Ceci est intéressant, mais la réponse simple est que je ne veux pas bloquer un CustomObject prêt à être mis à jour s'il ne dépend pas d'un autre CustomObject en cours de mise à jour. Je suppose que ce que je cherche est un gestionnaire de serrure de toutes sortes. –

0

Si vous utilisez une base de données standard de tout type, je suggère le dumping de ces verrous côté client entièrement en faveur des transactions et des verrous de table/rangée.

+0

La méthode PeformUpdate appelle un service Web pour obtenir les données, puis les enregistre dans la base de données avec les données du service Web. Je dois empêcher les appels simultanés au service Web et les mises à jour à la base de données. –

+0

Pourquoi utilisez-vous un webservice pour accéder à la base de données lorsque vous savez que vous allez avoir des mises à jour transactionnelles aux données? –

+0

L'appel de service Web obtient les données d'un tiers. Ces données sont stockées à la base de données par la suite. Je ne commence pas une transaction DB tant que les données ne reviennent pas du service. Je ne suis pas sûr de suivre ce que vous demandez. –

1

Verrouiller une chaîne n'est pas une bonne idée. Je propose deux alternatives:

  1. Utilisez un Dictionary<int,object> que le type CADENAS, et mettre un new object(); comme valeur.
  2. Créez une classe qui contient simplement l'ID; ce serait mieux pour la lisibilité si jamais vous voulez regarder votre classe LockPad pendant le débogage.

classe LockPad:

class LockPad { 
    public int Id { get; private set; } 

    public LockPad(int id) { 
     this.Id = id; 
    } 

    public override string ToString() { 
     return "lock of " + id.ToString(); 
    } 
} 

Ensuite, verrou sur cette classe.