Подтвердить что ты не робот

Дубликат возвращен Guid.NewGuid()?

У нас есть приложение, которое генерирует смоделированные данные для одного из наших сервисов для целей тестирования. Каждый элемент данных имеет уникальный Guid. Однако, когда мы запускали тест после некоторых незначительных изменений кода в симуляторе, все объекты, сгенерированные им, имели тот же Guid.

Был создан один объект данных, затем цикл for, в котором свойства объекта были изменены, включая новый уникальный Guid, и он был отправлен службе через удаленный доступ (сериализуемый, а не маршал-by-ref, если это то, что вы думаете), цикл и сделать это снова и т.д.

Если мы помещаем небольшой поток Thread.Sleep(...) внутри цикла, он генерирует уникальный идентификатор. Я думаю, что это красно-селедка. Я создал тестовое приложение, которое только что создало один guid за другим и не получило ни одного дубликата.

Моя теория заключается в том, что ИЛ был оптимизирован таким образом, который вызвал такое поведение. Но достаточно о моих теориях. Что вы думаете? Я открыт для предложений и способов тестирования.

ОБНОВЛЕНИЕ: Кажется, у меня много путаницы в моем вопросе, поэтому позвольте мне уточнить. Я НЕ считаю, что NewGuid() сломан. Ясно, что это работает. Все нормально! Однако есть ошибка, которая вызывает NewGuid(): 1) вызывается только один раз в моей петле 2) вызывается каждый раз в моем цикле, но назначается только один раз 3) что-то еще я не думал о

Эта ошибка может быть в моем коде (вероятно, MOST) или в оптимизации.

Итак, чтобы повторить мой вопрос, как мне отладить этот сценарий?

(и спасибо за отличную дискуссию, это действительно помогает мне прояснить проблему в моем сознании)

ОБНОВЛЕНИЕ # 2: Мне бы хотелось опубликовать пример, который показывает проблему, но та часть моей проблемы. Я не могу дублировать его за пределами всего набора приложений (клиент и серверы).

Вот соответствующий фрагмент, хотя:

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
}
4b9b3361

Ответ 1

Подходит ли асинхронный вызов, или объект билета переходит в другой поток на любом этапе.

В примере кода вы повторно используете один и тот же объект. Что делать, если Submit отправляет билет в фоновый поток после небольшой задержки (и не берет копию). При изменении CacheId вы фактически обновляете все ожидающие отправки. Это также объясняет, почему Thread.Sleep исправляет проблему. Попробуйте следующее:

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
}

Если по какой-то причине это невозможно, попробуйте это и посмотрите, все ли они одинаковы:

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

Ответ 2

Тысячи разработчиков используют Guids в .NET. Если Guid.NewGuid() имел какую-либо тенденцию вообще "застревать" по одному значению, проблема была бы встречена давно.

Ниже перечислены незначительные изменения кода. Тот факт, что Thread.Sleep (который меньше красной селедки, чем рыба, гниющая на солнце) "исправляет" вашу проблему, предполагает, что ваши свойства устанавливаются в какой-то странной способ, который не может вступить в силу до тех пор, пока цикл не остановит блокировку (либо по окончании, либо по Thread.Sleep). Я даже готов поспорить, что "незначительные изменения" состояли в reset всех свойствах из отдельного потока.

Если вы разместили код примера, это поможет.

Ответ 3

Это ошибка в вашем коде. Если вам удалось создать несколько указателей, это наиболее вероятное объяснение. Ключ здесь в вашем вопросе: "когда мы выполнили тест после некоторых незначительных изменений кода в симуляторе, все объекты, сгенерированные им, имели один и тот же Guid"

Ответ 4

Смотрите статью о том, как создается Guid.

Этот artcile пришел из ответа This.

Нижняя строка, если вы создаете GUID слишком быстро, и часы не перемещаются вперед, поэтому вы получаете то же самое. Однако когда вы засыпаете в нем, это работает, потому что часы переместились.

Ответ 5

Код в Submit и OrderTicket также будет полезен...

Вы повторно используете OrderTicket. Я подозреваю, что либо вы (или удаляете себя) выгружаете вызовы - возможно, в отношении # соединений/ограничений хоста - и подбираете последнее значение CacheId, когда он наконец отправляет их.

Если вы отлаживаете приложение или приложение Thread.Sleep, вы меняете время так, чтобы удаленный вызов заканчивался, прежде чем назначать новый CacheId.

Вы занимаетесь удалением удаленного вызова? Я думаю, что вызов синхронизации будет заблокирован, но я бы попробовал с пакетом sniffer как Wireshark, чтобы быть уверенным. Несмотря на это, просто переход на создание нового OrderTicket на каждой итерации, вероятно, сделает трюк.

Изменить: вопрос не в том, что NewGuid сломан... поэтому мой предыдущий ответ был удален.

Ответ 6

Я не знаю подробностей о том, как создаются GUID. Однако в настоящее время моя организация. это разведение GUID по ставке, которая заставила бы кроликов стыдиться. Поэтому я могу поручиться за то, что GUID не сломаны.

  • По возможности отправьте исходный код.. или приложение для воспроизведения клонов. Много раз я нахожу, что действие создания этого клон-приложения для воспроизведения проблемы показывает мне проблему.
  • Другой подход заключается в том, чтобы прокомментировать "те незначительные изменения". Если это устраняет проблему, вы можете затем треуготься, чтобы найти оскорбительную строку кода. Глаз-шарик незначительно меняется... Я имею в виду настоящий Жесткий.

Сообщите нам, как это происходит... это звучит интересно.

Ответ 7

Моя кишка говорит мне, что что-то происходит по этим строкам...

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

Записать значение CacheId в файл журнала каждый раз, когда его вызвал с помощью трассировки стека... Может быть, кто-то еще его устанавливает.