Comment verrouiller sur un entier en C#?
Est-il possible de se verrouiller sur un entier en C#? Les nombres entiers peuvent pas être utilisés avec serrure parce qu'ils sont en boîte (et de verrouillage verrouille uniquement sur les références).
Le scénario est le suivant: j'ai un forum de site web avec une modération de la fonctionnalité. Ce que je veux faire est de vous assurer que pas plus d'un modérateur peut modérer un post à un moment donné. Pour atteindre cet objectif, je veux verrouiller sur l'ID du post.
J'ai eu un couple d'idées jusqu'à présent (par ex. à l'aide d'un dictionnaire<int, object>), mais je suis à la recherche d'un mieux et de manière plus propre.
Des suggestions?
- hmm, peut-être vous pouvez créer une liste des postes actuellement en cours de modification et de vérifier?
- Qu'est-ce que la serrure? Si les modifications se produisent l'un après l'autre (ce qui est un verrou serait la cause), vous vous ne gagnez rien. Tous les DB mises à jour sont implicitement transactionnelle, ce qui signifie qu'ils se produisent l'un après l'autre et ne se mélangent pas.
- c'est un peu compliqué à expliquer mais en bref après le verrouillage, - je mettre à jour plusieurs bases de données (peut-être en cours d'exécution sur plusieurs serveurs de DB), par exemple, supprimer le post (dans une base de données), mise à jour de la modération de la base de données (si l'élément a été signalé .. etc), même dans la modération de la base de données, j'ai supprimer des enregistrements dans les tables et les insérer des enregistrements dans d'autres tables, ce qui pourrait causer une autre demande d'essayer de faire la même chose pour lancer une exception, il a tout pour être fait à la fois et les autres demandes doivent attendre
- Effectivement, c'est ce que je voulais dire quand j'ai mentionné à l'aide d'un dictionnaire, mais je crois que cela peut dégénérer très facilement
- Vous utilisez le mauvais outil pour le Travail, si vous voulez arrêter quelqu'un de la modification d'un enregistrement avec un Id particulier vous avez besoin de garder une liste de personnes interdites ID quelque part. vous ne pouvez pas verrouiller le nombre 1672 et empêcher toute autre personne de l'utiliser c'est juste de la folie. Cependant, vous pouvez vérifier pour voir si l'enregistrement 1672 a été verrouillé par un autre utilisateur et attendre jusqu'à ce que ce soit fait, ou feed-back que l'opération coudn'pas être réalisée car la somone d'autre a un verrou sur l'enregistrement.
- En fait, je ne m'inquiète pas si l'utilisateur modifie le post ou pas, il sera supprimé par le modérateur, ce que j'essaie de faire est de vous assurer que seul un modérateur peut supprimer un poste à la fois (ce qui implique des mises à jour des autres tables comme je l'ai expliqué dans le commentaire ci-dessus)
- Il semble que vous devez utiliser une transaction distribuée. Si vos bases de données, de les soutenir, il fonctionnera beaucoup mieux que d'essayer de mettre en œuvre un verrou dans la logique de l'application.
Vous devez vous connecter pour publier un commentaire.
J'aime le faire comme ceci
Ensuite, de se verrouiller sur un int vous simplement en utilisant la même synchroniseur à chaque fois)
Cette classe renvoie le même verrou de l'objet lorsqu'il a reçu le même index à deux reprises. Lorsqu'un nouvel indice vient, c'est de créer un objet, de le retourner, et la stocke dans le dictionnaire pour la prochaine fois.
Il peut être facilement modifié pour fonctionner de manière générique avec tout
struct
ou type de valeur, ou à êtrestatic
de sorte que la synchronisation de l'objet n'a pas à être passé autour.this[int index]
vous pourriez essayer d'obtenir le même résultat à l'extérieur de la serrure de la première, et qu'une fois de plus à l'intérieurSi c'est un site puis à l'aide d'un processus de verrouillage n'est probablement pas la meilleure approche, car si vous avez besoin à l'échelle du site sur plusieurs serveurs, ou d'ajouter un autre site d'hébergement d'une API (ou n'importe quoi d'autre qui exigerait un autre processus accédant aux mêmes données d'exister), alors tous vos verrouillage stratégies sont immédiatement inefficace.
Je serais enclin à regarder dans la base de données en fonction de verrouillage pour cela. L'approche la plus simple est d'utiliser le verrouillage optimiste avec quelque chose comme un horodatage quand le poste a été mis à jour, et à rejeter les mises à jour apportées à un poste, à moins que les horodateurs match.
J'ai lu beaucoup de commentaires mentionnant que le verrouillage n'est pas sans danger pour les applications web, mais, à l'exception des batteries de serveurs web, je n'ai pas vu d'explications du pourquoi. Je serais intéressé à entendre les arguments contre elle.
J'ai un besoin similaire, bien que je me suis mise en cache de redimensionner les images sur le disque dur (ce qui est évidemment une action locale, donc une batterie de serveurs web scénario n'est pas un problème).
Ici est une version refaite de ce que @Configurateur posté. Il comprend un couple de fonctionnalités que @Configurateur ne comprend pas:
Voici le code...
Voici comment vous pouvez l'utiliser...
Je serais personnellement aller avec soit Greg ou Konrad approche.
Si vraiment vous ne voulez
lock
contre l'ID de la poste elle-même (et en supposant que votre code ne jamais être en cours d'exécution dans un seul processus), quelque chose comme ce n'est pas trop sale:Cette option repose sur la bonne réponse fournie par le configurateur avec les modifications suivantes:
Le code:
Aussi, juste pour être complet, il y a l'alternative de la chaîne de stage: -
Voir cette réponse quelques informations:
Le seul avantage de la chaîne de stage approche est que vous n'avez pas besoin de gérer un dictionnaire. Je préfère le dictionnaire de serrures approche que le stagiaire approche fait beaucoup d'hypothèses sur la façon dont la chaîne de stage œuvres et qu'il continuera à travailler dans ce sens. Il utilise également un stage pour quelque chose, il n'a jamais été question /conçu pour faire.
Pourquoi ne pas verrouiller sur l'ensemble de l'affichage à la place de son ID?
Coresystem sur codeplex a deux classes pour la synchronisation des threads basée sur les types de valeur, pour les détails, voir http://codestand.feedbook.org/2012/06/lock-on-integer-in-c.html
Je doute que vous devez utiliser une base de données ou O/S niveau de fonctionnalité comme les verrous pour une entreprise niveau de décision. Serrures engager des frais généraux lors de la tenue pour le temps long (et dans ces contextes, rien au-delà de quelques centaines de millisecondes, c'est une éternité).
Ajouter un champ de statut de la poste. Si vous faites affaire avec plusieurs therads directement, alors vous pouvez utiliser l'O/S verrous de niveau -- définir l'indicateur.
Vous besoin d'une approche différente de cette.
Rappeler qu'avec un site web, vous n'avez pas réellement un live application en cours d'exécution sur l'autre côté qui répond à ce que fait l'utilisateur.
Vous recommencez en fait une mini-application, qui renvoie à la page web, puis le serveur est fait. Que l'utilisateur finit par l'envoi de certaines données est un sous-produit, pas une garantie.
Donc, vous avez besoin de verrouiller à persister après l'application a retourné à la modération de la page retour à l'animateur, puis relâchez-le lorsque le modérateur est fait.
Et vous avez besoin pour traiter un certain type de l'expiration du délai, si le modérateur ferme son navigateur après l'obtention de la modération de la page de retour, et donc ne communique jamais de retour avec le serveur qu'il/elle est fait avec le processus de modération pour ce post.
Idéalement, vous pouvez éviter tous les complexes et fragiles et C# de verrouillage et de le remplacer avec de verrouillage de base de données, si vos transactions sont conçus correctement, alors vous devriez être capable de s'en sortir avec les transactions DB seulement.
Deux en boîte entiers qui ont la même valeur sont complètement indepent objets.
Donc si vous voulez faire cela, votre idée de Dictionnaire serait probablement la voie à suivre. Vous auriez besoin de synchroniser l'accès à un dictionnaire pour assurez-vous que vous êtes toujours obtenir la même instance. Et vous auriez le problème du dictionnaire de croissance en taille.
C# verrouillage pour la sécurité des threads et ne fonctionne pas de la façon dont vous le souhaitez pour les applications web.
La solution la plus simple est d'ajouter une colonne à la table que vous souhaitez verrouiller et quand la somone serrures d'écrire la db que cette colonne est verrouillé.
Ne laissez personne d'ouvrir un post dans le mode edit, si la colonne est verrouillé pour modification.
Autrement maintenir une liste statique de verrouillé Id d'entrée et la comparer à ce que, avant d'autoriser une modification.
Vous voulez assurez-vous que la suppression ne se produit pas deux fois?
C'est à peu près la syntaxe SQL server, je ne suis pas familier avec MyISAM. Mais il permet de procédures stockées. Je devine que vous pouvez se moquer d'une procédure similaire.
De toute façon, cela fonctionne pour la majorité des cas. La seule fois où il échouera est que si deux modérateurs soumettre à presque exactement à la même heure, et la exists() la fonction passe sur une requête juste avant de le SUPPRIMER instruction s'exécute sur l'autre demande. Je me ferait un plaisir de les utiliser pour un petit site. Vous pourriez prendre une étape supplémentaire et vérifier que les supprimer réellement supprimé une ligne avant de poursuivre avec le reste, ce qui permettrait de garantir l'atomicité de tout cela.
En essayant de créer une serrure à code, pour ce cas d'utilisation, je considère que très peu pratique. Vous ne perdez rien pour avoir deux modérateurs de la tentative de suppression d'un post, avec un succès, et l'autre n'ayant aucun effet.
Vous devez utiliser une synchronisation de l'objet comme ceci:
Mais cette approche ne doit pas être utilisé dans une application web scénario.