Question

Nous disposons d'une application qui génère des données simulées pour l'un de nos services à des fins de test. Chaque élément de données a un Guid unique. Cependant, lorsque nous avons exécuté un test après quelques modifications mineures du code dans le simulateur, tous les objets générés par celui-ci avaient le même Guid.

Un seul objet de données a été créé, puis une boucle for dans laquelle les propriétés de l’objet ont été modifiées, y compris un nouveau Guid unique, et il a été envoyé au service via remoting (sérialisable, pas marshal-by-ref, si c'est ce que vous pensez), boucle et refaire, etc.

Si nous mettons un petit Thread.Sleep (...) à l'intérieur de la boucle, cela générera des identifiants uniques. Je pense que c'est un hareng rouge cependant. J'ai créé une application de test qui vient de créer un guide après l'autre sans obtenir un seul duplicata.

Ma théorie est que l'IL a été optimisé de manière à provoquer ce comportement. Mais assez parlé de mes théories. Qu'est-ce que tu penses? Je suis ouvert aux suggestions et aux moyens de le tester.

MISE À JOUR: Il semble y avoir beaucoup de confusion dans ma question, alors laissez-moi préciser. Je ne pense pas que NewGuid () est cassé. Clairement ça marche. C'est bien! Il y a un bogue quelque part, qui force NewGuid () à: 1) être appelé une seule fois dans ma boucle 2) être appelé à chaque fois dans ma boucle mais assigné une seule fois 3) autre chose que je n'ai pas pensé

Ce bogue peut être dans mon code (LE PLUS probable) ou dans l'optimisation quelque part.

Pour réitérer ma question, comment devrais-je déboguer ce scénario?

(et merci pour la grande discussion, cela m'aide vraiment à clarifier le problème dans mon esprit)

MISE À JOUR N ° 2: J'aimerais publier un exemple montrant le problème, mais cela fait partie de mon problème. Je ne peux pas le dupliquer en dehors de toute la suite d'applications (client et serveurs).

Voici un extrait pertinent:

OrderTicket ticket = new OrderTicket(... );

for( int i = 0; i < _numOrders; i++ )
{
    ticket.CacheId = Guid.NewGuid();
    Submit( ticket );  // note that this simply makes a remoting call
}
Était-ce utile?

La solution

Submit effectue-t-il un appel asynchrone ou l'objet de ticket est-il inséré dans un autre thread à tout moment?

Dans l'exemple de code, vous réutilisez le même objet. Que se passe-t-il si Submit envoie le ticket dans un thread d'arrière-plan après un court délai (et ne prend pas de copie). Lorsque vous modifiez le CacheId, vous mettez à jour tous les envois en attente. Cela explique également pourquoi un Thread.Sleep résout le problème. Essayez ceci:

for( int i = 0; i < _numOrders; i++ )
{
    OrderTicket ticket = new OrderTicket(... );
    ticket.CacheId = Guid.NewGuid();
    Submit( ticket );  // note that this simply makes a remoting call
}

Si, pour une raison quelconque, cela n'est pas possible, essayez-le et voyez si elles sont toujours les mêmes:

ticket.CacheId = new Guid("00000000-0000-0000-0000-" + 
     string.Format("{0:000000000000}", i));

Autres conseils

Des milliers de développeurs utilisent Guids dans .NET. Si Guid.NewGuid () avait la moindre tendance à rester "bloqué" sur une valeur, le problème aurait été rencontré il y a longtemps.

Les modifications mineures du code sont le coupable certain. Le fait que Thread.Sleep (qui est inférieur à un hareng rouge qu'un poisson en décomposition au soleil) "fixe" votre problème suggère que vos propriétés sont définies d'une manière étrange qui ne peut prendre effet que lorsque la boucle cesse de bloquer (en finissant ou par Thread.Sleep). Je serais même prêt à parier que le "changement mineur" était de réinitialiser toutes les propriétés à partir d'un thread séparé.

Si vous publiez un exemple de code, cela vous aidera.

C'est un bug dans votre code. Si vous avez réussi à générer plusieurs GUID, c'est l'explication la plus probable. L’indice se trouve dans votre question: "Lorsque nous avons exécuté un test après quelques modifications mineures du code dans le simulateur , tous les objets générés par celui-ci avaient le même Guid"

. "

Voir cet article sur le fonctionnement d'un guide est créé.

Cet article provient de la This answer.

Si vous créez les GUID trop rapidement et que l’horloge n’a pas avancé, c’est la raison pour laquelle vous obtenez le même. Cependant, lorsque vous mettez un sommeil réparateur, cela fonctionne car l'horloge a été déplacée.

Le code dans Submit et OrderTicket serait également utile ...

Vous réutilisez OrderTicket. Je soupçonne que vous (ou le serveur à distance lui-même) chargez les appels en lots - probablement en ce qui concerne le nombre de connexions / limites d’hôte - et que vous récupérez la dernière valeur de CacheId lorsqu’il les envoie enfin.

Si vous déboguez ou que Thread soit installé, vous modifiez le minutage de sorte que l'appel distant se termine avant que vous n'affectiez un nouveau CacheId.

Avez-vous synchronisé l'appel à distance? Je penserais qu'un appel de synchronisation bloquerait - mais je vérifierais avec un renifleur de paquets comme Wireshark pour en être sûr. Quoi qu’il en soit, le simple fait de créer un nouveau OrderTicket à chaque itération ferait probablement l'affaire.

Éditer: La question n'est pas de savoir si NewGuid est cassé ... donc ma réponse précédente a été supprimée.

Je ne connais pas les détails de la façon dont les GUID sont générés .. pour le moment. Cependant actuellement mon org. multiplie les GUID à un rythme qui ferait honte aux lapins. Je peux donc garantir que les GUID ne sont pas encore brisés .. .

  • Publiez le code source si possible .. ou une application de reproduction de clone. Plusieurs fois, je trouve que le fait de créer cette application clone pour reproduire le problème montre le problème.
  • L’autre approche consisterait à commenter "ces modifications mineures". Si cela résout le problème, vous pouvez alors trianguler pour trouver la ligne de code incriminée. Le globe oculaire de la mineure change fort ... Je veux dire très fort.

Faites-nous savoir comment ça se passe ... cela semble intéressant.

Mon instinct me dit qu'il se passe quelque chose dans ce sens ...

class OrderTicket 
{
   Guid CacheId {set {_guid = new Guid("00000000-0000-0000-0000-");}
}

Consignez la valeur de CacheId dans un fichier journal chaque fois qu’elle est appelée avec une trace de pile ... Peut-être que quelqu'un d'autre la définit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top