1

次のコードがあります。Windows Server 2008 では、プログラムは正しく、期待どおりに実行されます。10個の異なるIDを出力します。

しかし、Windows Server 2003 で実行すると、プログラムが正しくありません。10 個の ID が出力されますが、一部の ID が重複しています。ロックが効かないようです。

を設定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;
    }
}
4

5 に答える 5

3

ロックは完全に不要です。問題はDateTime.Now、粒度が 15 ミリ秒程度しかないことです (システムによって異なります)。そもそも時間を ID として使用しないでください。代わりに、次のようなことを簡単に行うことができます。

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

    private static long Next()
    {
        return Interlocked.Increment(ref _id);
    }
}
于 2011-04-22T03:43:37.573 に答える
2

キーを生成するこの方法から離れることをお勧めしますが、他の条件に制約されている場合は、待機を強制せずにコードを修正できる 1 つの方法は、最後に生成された ID への参照を保持することです。古いもの、sleep(10) などに一致します。

これにより、コードの既存のすべてのプロパティが保持されます。主な理由は、提示された他の例のような単一のセッションではなく、プログラムの実行間で増加し続けることだと思います。

于 2011-04-22T04:09:55.503 に答える
1

Thread.Sleep のパラメーターはミリ秒単位です。より大きな数値を選択してください。または、Guid.NewGuid() を使用して、時間を無駄にすることなく実際に一意の ID を生成します。

于 2011-04-22T03:16:10.927 に答える
1

あなたDateTime.Ticksのために働くでしょうか?100ナノ秒の分解能なので、うまくいくようです。IMO、何もロックする必要はありません。

于 2011-04-22T03:35:45.923 に答える
0

ロックしたので、以前の値を保存して、等しいかどうかを比較してください。等しければ、戻らず、スリープしてループで再試行します。

個人的には、このアプローチは最悪だと思います。GUID を使用してください。GUID はあなたの味方です。

于 2011-04-22T04:19:30.693 に答える