10

テスト目的で、サービスの 1 つにシミュレートされたデータを生成するアプリケーションがあります。各データ項目には一意の Guid があります。ただし、シミュレーターにいくつかの小さなコード変更を加えた後にテストを実行すると、シミュレーターによって生成されたすべてのオブジェクトが同じ Guid を持っていました。

単一のデータ オブジェクトが作成された後、新しい一意の Guid を含むオブジェクトのプロパティが変更された for ループがあり、リモート処理 (参照によるマーシャルではなくシリアル化可能) を介してサービスに送信されました。考えている)、ループしてもう一度やり直すなど。

小さな Thread.Sleep( ...) をループ内に配置すると、一意の ID が生成されます。私はそれが赤いニシンだと思います。次々と guid を作成しただけのテスト アプリを作成し、単一の重複を取得しませんでした。

私の理論は、IL がこの動作を引き起こす方法で最適化されたというものです。しかし、私の理論については十分です。どう思いますか?私はそれをテストするための提案と方法を受け入れます。

更新: 私の質問には多くの混乱があるようですので、明確にさせてください。NewGuid() が壊れているとは思いません。明らかにそれは機能します。大丈夫だよ!ただし、どこかにバグがあり、それにより NewGuid() が次のいずれかになります: 1) ループ内で 1 回だけ呼び出される 2) ループ内で毎回呼び出されるが、1 回だけ割り当てられる 3) 考えもしなかった何か

このバグは、私のコード (ほとんどの場合) または最適化のどこかにある可能性があります。

私の質問を繰り返しますが、このシナリオをどのようにデバッグすればよいですか?

(そして素晴らしい議論をありがとう、これは私の頭の中の問題を明確にするのに本当に役立っています)

更新#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
}
4

7 に答える 7

21

Submitは非同期呼び出しを実行しますか、またはチケットオブジェクトは任意の段階で別のスレッドに入りますか。

コード例では、同じオブジェクトを再利用しています。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));
于 2008-11-20T00:16:10.707 に答える
7

何千人もの開発者が .NET で Guid を使用しています。Guid.NewGuid() が 1 つの値に「スタック」する傾向があった場合、問題はずっと前に発生していたはずです。

マイナーコードの変更は、ここでの確実な原因です。Thread.Sleep (太陽の下で腐った魚よりも赤いニシンではありませ) が問題を「修正」するという事実は、ループがブロックを停止するまで有効にならない奇妙な方法でプロパティが設定されていることを示唆しています (終了または Thread.Sleep による)。「小さな変更」は、別のスレッドからすべてのプロパティをリセットすることであることに賭けても構わないと思います。

サンプルコードを投稿した場合、それは役に立ちます。

于 2008-11-19T02:24:37.220 に答える
3

それはあなたのコードのバグです。複数の GUID を生成できた場合、それが最も可能性の高い説明です。手がかりはあなたの質問にあります

于 2008-11-19T01:54:36.237 に答える
2

Guid の作成方法については、この記事を参照してください。

この記事は、この回答からのものです。

要するに、GUID の作成が速すぎて時計が前に進んでいない場合、同じものをいくつか取得しているのです。ただし、睡眠を入れると、時計が動いたので機能します。

于 2008-11-19T02:03:29.977 に答える
2

Submit と OrderTicket のコードも役に立ちます...

OrderTicket を再利用しています。あなた(またはリモーティング自体)が呼び出しをバッチ処理していると思われます-おそらく接続数/ホスト制限に関して-そして最終的にそれらを送信するときにCacheIdの最後の値を取得します。

アプリをデバッグまたは Thread.Sleep する場合は、タイミングを変更して、新しい CacheId を割り当てる前にリモート呼び出しが終了するようにします。

リモート呼び出しを非同期にしていますか? 同期呼び出しがブロックされると思いますが、Wireshark のようなパケット スニファで確認します。とにかく、反復ごとに新しい OrderTicket を作成するように変更するだけで、おそらくうまくいくでしょう。

編集:質問はNewGuidが壊れていることではありません...したがって、以前の回答は削除されました

于 2008-11-19T02:21:27.320 に答える
1

GUID の生成方法の詳細はまだわかりません。しかし、現在私の組織。うさぎを恥じさせる速度で GUID を繁殖させています。したがって、 GUID が壊れていないという事実を保証できます.. まだ.

  • 可能であればソースコードを投稿するか、複製再現アプリを投稿してください。問題を再現するためにそのクローンアプリを作成する行為が問題を示していることがよくあります。
  • もう 1 つのアプローチは、「マイナーな変更」をコメントアウトすることです。これで問題が解決した場合は、三角形化して問題のあるコード行を見つけることができます。目玉マイナーチェンジハード…つまりリアルハード。

それがどうなるか教えてください...これは面白そうです。

于 2008-11-19T04:43:49.857 に答える
0

私の腸は、これらの線に沿って何かが起こっていると私に言っています...

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

スタックトレースで呼び出されるたびに、CacheIdの値をログファイルに記録します...他の誰かが設定している可能性があります。

于 2008-11-20T00:40:34.217 に答える