2012-03-08 35 views
-5

編集:なぜ5つのダウンボントを取得したのですが、何のコメントもしていないので、私は質問を再フォーマットしようとしました。私は人々が多くのテキストを見て、多分ここに質問さえないと思うので、投票があると仮定することができます。コンソールアプリケーションの奇妙な問題

(誤って)むしろ奇妙に動作するコードを書いています。コードが他のコンピュータでも同じように動作しないようですので、問題を再現できない場合は私に怒らないようにしてください。

GUIDで異な​​るバイトが出現する頻度で、面白かったです。私はguidの文字列表現には常に "4"が含まれていたことに気づいた。 Wikipediaでそれを読むのではなく、ちょっとした「オリジナルの研究」をして、しばらくの間あなた自身の考えをするのが楽しいかもしれないので、私はそれが何であるか考えようとしました。 (その後、wikiを読んでください!)

"バースト"機能を使用しようとすると、私のマシン上で奇妙な問題が発生します。あなたの環境で再現可能であれば、アプリケーションを実行してBを押すことで再作成することができます。これは100ステップのバーストを引き起こすと思われます(100個の新しいガイドを作成し、表示された周波数をバースト、コンソールへの書き込みはとてもばかげて遅いので)。しかし、実際には1つのステップに過ぎません!

バースト変数が割り当てられているProcessKey()にブレークポイントを設定しました。メソッドから抜け出すと、スレッド出力がデバッグ出力に出ていることがわかります。これは偶然ではありません。それは毎回確実に起こります。次に、私の時計は、前のステップで1000に割り当てられたばかりのバースト変数を示しています...値が0です。

なぜこれが起こりますか?私は間違ったことをしましたか?私はSTAを指定する属性がないことに気が付きましたが、とにかくこれらのものが何であるかを実感したことはありませんでした。コンソールアプリケーションのテンプレートから何も削除していませんでした(VS- ...

最後に、アプリケーションはカーソルを戻し、テキストを何度も上書きします。これは、すべての出力を一度に表示できるほどコンソールウィンドウを高くすることができない場合にはうまく機能しないため、コンソールフォントを操作する(またはコンソールの幅を変更すると、私はテストしていない)。パターンは4列の出力で完全に規則的になります(コンソールが80文字幅の場合は4列になります)。

(場合に応じて、またはしない)を再生するためにコード:

using System; 
using System.Diagnostics; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static bool running, exit; 
     static int burst; 
     static long guidCount = 0; 
     static long[] counts = new long[256]; 
     static DateTime nextReport = DateTime.MinValue; 
     static readonly TimeSpan reportInterval = TimeSpan.FromSeconds(0.25); 


     static void Main(string[] args) 
     { 
      Console.WindowHeight = (int)(0.8*Console.LargestWindowHeight); 

      WriteLine(ConsoleColor.White, "X - Exit | P - Pause | S - Step (hold for Slow) | B - Burst\r\n"); 
      WriteLine("Auto-reporting interval = {0}.", reportInterval); 

      Guid guid; 
      byte[] bytes; 

      var cursorPos = new CursorLocation(); 

      while (!exit) 
      { 
       if (Console.KeyAvailable) 
       { 
        ProcessKey(Console.ReadKey(true)); 
       } 

       if (running || burst > 0) 
       { 
        guid = Guid.NewGuid(); 
        bytes = guid.ToByteArray(); 
        ++guidCount; 

        for (int i = 0; i < 16; i++) 
        { 
         var b = bytes[i]; 
         ++counts[b]; 
        } 

        if (burst > 0) --burst; 

        if (burst == 0 || DateTime.Now > nextReport) 
        { 
         burst = -1; 
         cursorPos.MoveCursor(); 
         ReportFrequencies(); 
        } 
       } 
       else 
        Thread.Sleep(20); 
      } 
     } 


     static void ProcessKey(ConsoleKeyInfo keyInfo) 
     { 
      switch (keyInfo.Key) 
      { 
       case ConsoleKey.P: 
        running = !running; 
        break; 

       case ConsoleKey.B: 
        burst = 100; 
        break; 

       case ConsoleKey.S: 
        burst = 1; 
        break; 

       case ConsoleKey.X: 
        exit = true; 
        break; 
      } 
     } 


     static void ReportFrequencies() 
     { 
      Write("\r\n{0} GUIDs generated. Frequencies:\r\n\r\n", guidCount); 

      const int itemWidth = 9; 
      int colCount = Console.WindowWidth/(itemWidth*2); 

      for (int i = 0; i < 256; i++) 
      { 
       var f = (double)counts[i]/(16 * guidCount); 
       Write(RightAdjust(itemWidth, "{0:x}", i)); 
       Write(GetFrequencyColor(f), " {0:p}".PadRight(itemWidth), f); 
       if ((i + 1) % colCount == 0) Write("\r\n"); 
      } 

      nextReport = DateTime.Now + reportInterval; 
     } 


     static ConsoleColor GetFrequencyColor(double f) 
     { 
      if (f < 0.003) return ConsoleColor.DarkRed; 
      if (f < 0.004) return ConsoleColor.Green; 
      if (f < 0.005) return ConsoleColor.Yellow; 
      return ConsoleColor.White; 
     } 


     static string RightAdjust(int w, string s, params object[] args) 
     { 
      if (args.Length > 0) 
       s = string.Format(s, args); 
      return s.PadLeft(w); 
     } 

     #region From my library, so I need not include that here... 
     class CursorLocation 
     { 
      public int X, Y; 
      public CursorLocation() 
      { 
       X = Console.CursorLeft; 
       Y = Console.CursorTop; 
      } 

      public void MoveCursor() 
      { 
       Console.CursorLeft = X; 
       Console.CursorTop = Y; 
      } 
     } 


     static public void Write(string s, params object[] args) 
     { 
      if (args.Length > 0) s = string.Format(s, args); 
      Console.Write(s); 
     } 


     static public void Write(ConsoleColor c, string s, params object[] args) 
     { 
      var old = Console.ForegroundColor; 
      Console.ForegroundColor = c; 
      Write(s, args); 
      Console.ForegroundColor = old; 
     } 


     static public void WriteNewline(int count = 1) 
     { 
      while (count-- > 0) Console.WriteLine(); 
     } 


     static public void WriteLine(string s, params object[] args) 
     { 
      Write(s, args); 
      Console.Write(Environment.NewLine); 
     } 


     static public void WriteLine(ConsoleColor c, string s, params object[] args) 
     { 
      Write(c, s, args); 
      Console.Write(Environment.NewLine); 
     } 
     #endregion 
    } 
} 
+5

私はアプリを実行し、ProcessKeyメソッドをステップオーバー(F10)し、バーストが正しく設定されています。私はまた(F11)を踏んだ後に脱出(Shift + F11)し、両方の状況でバースト= 100を見ます。あなたが何をしているのか分かりません。私はGuidsがあなたのマシンの側面を取り入れているので、私は一様な配布を期待していないと思います。そうしないと、システム間のGuidの衝突の機会があります。結局のところ、Globally Unique IDentifierであるはずです。 – Lazarus

+1

これらのスレッド出口は、コードではなくデバッガのアクティビティに関連していますか? – dsolimano

+0

ありがとうございます。私は誰かが理由を知らせるためにコメントを残すことを望む。私は**最初の文**を知っています(短くて甘い "これを試してください")は質問ではなく、疑問に思われるかもしれません。しかし、人々が実際に読んでいると、小さな背景、特定の質問、結果を再現するためのコードがたくさんあることがわかります。 –

答えて

1

Ehem。私はこれをコード化したものとは別のコンピュータであるHTPCでコードを実行しようとしましたが、今は問題を再現できません。つまり、私はバーストが一歩に進むのを観察しますが、それは自分のコードの論理エラーによるものです(レポート間隔に達するとバーストは-1に設定されます)。 ではないと信じるのは難しい私のブレークポイントを設定し、ステップを踏み、変数が破壊されるのを見ました。私が見たと思ったことを確かめるために何度か奇妙なことを知っていたからです。しかし、フレームワーク/ clrのような奇妙で深いバグに遭遇したことを信じるのは難しいです。特に、私のコードにはデバッガを最初に付け加えたバグがあると考えています。

いずれにせよ、私はそれを閉じたものとしてマークします。誰かがそれを試してみたいと思えば、ここに改訂コードを投稿してください。私はバグを修正し、出力をよりコンパクトにしました。これは22インチのfull-HD_oneよりも寛大なスクリーンではうまく動作しません。コンソールの幅に関係なく8カラムを使用します。大部分の人々は標準的な80文字幅を使用しています。これには8列が入ります。

誰かがこれを実行して気づいたら、結果を投稿してください(ちょうどPを押すと安定した周波数が得られます)。ステップ/バーストは世代が少ない世代に見えるような愚かなものです。

 
0x00 - 0x3f 0.34% 
0x40 - 0x4f 0.73% 
0x50 - 0x7f 0.34% 
0x80 - 0xbf 0.44% 
0xc0 - 0xff 0.34% 

これは意味します:バイト0x00が、この特定のケースで(509194を生成し、すべてのGUIDにそれぞれが構成されたすべてのバイトの0.34パーセントをが0x3fするが、私は、この結果、すべてを取得する私のHTPCで、私はこの結果を得ます100,000人以上の指導者がいる時間)。 3つの非常に異なるグループがあります。そして、今、私が今ウィキペディアのGuidsについて読んでいれば、なぜそれが理解できるのでしょうか。しかし、私の「発見」が私が始める前に知っていたものだったら、これをするのは楽しいことではありません。 :)

using System; 
using System.Diagnostics; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static bool running, exit; 
     static int burst; 
     static long guidCount = 0; 
     static long[] counts = new long[256]; 
     static DateTime nextReport = DateTime.MinValue; 
     static readonly TimeSpan reportInterval = TimeSpan.FromSeconds(1); 


     static void Main(string[] args) 
     { 
      Console.WindowHeight = (int)(0.8 * Console.LargestWindowHeight); 

      WriteLine(ConsoleColor.White, "X - Exit | P - Run/Pause | S - Step (hold for Slow) | B - Burst"); 
      WriteLine("Press P, S or B to make something happen.", reportInterval); 

      Guid guid; 
      byte[] bytes; 

      var cursorPos = new CursorLocation(); 

      while (!exit) 
      { 
       if (Console.KeyAvailable) 
       { 
        ProcessKey(Console.ReadKey(true)); 
       } 

       if (running || burst > 0) 
       { 
        guid = Guid.NewGuid(); 
        bytes = guid.ToByteArray(); 
        ++guidCount; 

        for (int i = 0; i < 16; i++) 
        { 
         var b = bytes[i]; 
         ++counts[b]; 
        } 

        if (burst > 0) --burst; 

        if (burst == 0 && DateTime.Now > nextReport) 
        { 
         cursorPos.MoveCursor(); 
         ReportFrequencies(); 
        } 
       } 
       else 
        Thread.Sleep(20); 
      } 
     } 


     static void ProcessKey(ConsoleKeyInfo keyInfo) 
     { 
      switch (keyInfo.Key) 
      { 
       case ConsoleKey.P: 
        running = !running; 
        break; 

       case ConsoleKey.B: 
        burst = 100; 
        break; 

       case ConsoleKey.S: 
        burst = 1; 
        break; 

       case ConsoleKey.X: 
        exit = true; 
        break; 
      } 
     } 


     static void ReportFrequencies() 
     { 
      Write("\r\n{0} GUIDs generated. Frequencies (%):\r\n\r\n", guidCount); 

      const int itemWidth = 11; 
      const int colCount = 8; // Console.WindowWidth/(itemWidth + 2); 

      for (int i = 0; i < 256; i++) 
      { 
       var f = (double)counts[i]/(16 * guidCount); 
       var c = GetFrequencyColor(f); 
       Write(c, RightAdjust(3, "{0:x}", i)); 
       Write(c, " {0:0.00}".PadRight(itemWidth), f*100); 
       if ((i + 1) % colCount == 0) Write("\r\n"); 
      } 

      nextReport = DateTime.Now + reportInterval; 
     } 


     static ConsoleColor GetFrequencyColor(double f) 
     { 
      if (f < 0.003) return ConsoleColor.DarkRed; 
      if (f < 0.004) return ConsoleColor.Green; 
      if (f < 0.005) return ConsoleColor.Yellow; 
      return ConsoleColor.White; 
     } 


     static string RightAdjust(int w, string s, params object[] args) 
     { 
      if (args.Length > 0) 
       s = string.Format(s, args); 
      return s.PadLeft(w); 
     } 

     #region From my library, so I need not include that here... 
     class CursorLocation 
     { 
      public int X, Y; 
      public CursorLocation() 
      { 
       X = Console.CursorLeft; 
       Y = Console.CursorTop; 
      } 

      public void MoveCursor() 
      { 
       Console.CursorLeft = X; 
       Console.CursorTop = Y; 
      } 
     } 


     static public void Write(string s, params object[] args) 
     { 
      if (args.Length > 0) s = string.Format(s, args); 
      Console.Write(s); 
     } 


     static public void Write(ConsoleColor c, string s, params object[] args) 
     { 
      var old = Console.ForegroundColor; 
      Console.ForegroundColor = c; 
      Write(s, args); 
      Console.ForegroundColor = old; 
     } 


     static public void WriteNewline(int count = 1) 
     { 
      while (count-- > 0) Console.WriteLine(); 
     } 


     static public void WriteLine(string s, params object[] args) 
     { 
      Write(s, args); 
      Console.Write(Environment.NewLine); 
     } 


     static public void WriteLine(ConsoleColor c, string s, params object[] args) 
     { 
      Write(c, s, args); 
      Console.Write(Environment.NewLine); 
     } 
     #endregion 
    } 
} 

あなたの結果、女性、紳士を投稿してください。 :)

+0

できるだけ早く私が覚えていれば、私はこの答えを受け入れるでしょう。一方、stackoverflowは私自身の質問にも私自身の答えをそのようにマークすることはできませんので、私を憎むことはありません。 (私は、彼らの "信用"システムがどういうわけか自分の質問に答えることを無視していると思うべきです。なぜこの方針が適切なのかわかりません)。 –