c # Блокировка с помощью Thread.Sleep не работает - PullRequest
1 голос
/ 22 апреля 2011

У меня есть следующий код. В Windows Server 2008 программа работает правильно и работает как положено. Выводит 10 разных идентификаторов.

Однако, когда я запускаю его в Windows Server 2003, программа работает неправильно. Он выводит 10 идентификаторов, но некоторые идентификаторы являются дубликатами. Кажется, что замок не работает.

Если я установил Thread.Sleep(500), он работает правильно на Windows Server 2003.

class Test
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine(Util.GetId());
        }
        Console.ReadLine();
    }
}

public class Util
{
    private static object idlock = new object();

    public static string GetId()
    {
        string id = "";
        lock (idlock)
        {
            Thread.Sleep(1);
            id = System.DateTime.Now.ToString("yyMMddHHmmssffff");
        }
        return id;
    }
}

Ответы [ 5 ]

3 голосов
/ 22 апреля 2011

Блокировка совершенно не нужна; проблема в том, что DateTime.Now имеет только гранулярность ~ 15 мс или около того (в зависимости от вашей системы). Во-первых, не используйте время как идентификатор; Вы можете легко сделать что-то вроде этого:

public static class Util
{
    static long _id;
    public static string GetId()
    {
        return Next().ToString("0000000000000000");
    }

    private static long Next()
    {
        return Interlocked.Increment(ref _id);
    }
}
2 голосов
/ 22 апреля 2011

Хотя я и предлагаю отказаться от этого метода генерации ключей, но если вас ограничивают другие условия, то один из способов исправить код, не заставляя ждать, - это сохранить ссылку на последний сгенерированный идентификатор, тогда как толькосгенерированный идентификатор по-прежнему совпадает со старым, sleep (10) или около того.

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

1 голос
/ 22 апреля 2011

Будет ли DateTime.Ticks работать на вас?Он имеет разрешение 100 наносекунд, так что, похоже, он может работать.Вам тоже не нужно ничего блокировать, ИМО.

1 голос
/ 22 апреля 2011

Thread.Sleep параметр в миллисекундах, выберите большее число. Или используйте Guid.NewGuid (), чтобы сгенерировать действительно уникальный идентификатор, не теряя времени.

0 голосов
/ 22 апреля 2011

Теперь, когда вы блокируете, попробуйте сохранить предыдущее значение и сравнить на равенство. Если все равно, не возвращайтесь, а, скорее, спите и попробуйте снова, в цикле.

Лично я думаю, что такой подход - отстой. Используйте GUID, они ваши друзья.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...