2012-03-08 7 views
-5

편집 : 왜 5 개의 downvotes를 얻었지만 그 이유에 대해 아무 말도하지 않고서, 나는 그 질문을 다시 형식화하려고 시도했다. 나는 사람들이 많은 텍스트를보고 아마 여기에 질문조차 없다고 생각하기 때문에 투표가 있다고 가정 할 수 있습니다.콘솔 앱의 이상한 문제

(오) 오히려 이상하게 행동하는 코드를 작성했습니다. 코드가 다른 컴퓨터에서 같은 방식으로 실행되지 않는 것 같습니다. 문제를 재현 할 수 없다면 저에게 화를 내지 마십시오.

GUID에서 다른 바이트가 나타나는 빈도로 재미있게 보였습니다. 나는 guid의 문자열 표시가 항상 "4"를 포함한다는 것을 알아 챘다. Wikipedia에서이 책을 읽는 대신, "독창적 인 연구"를 조금 해보고 자신의 생각을 한 번 해보는 것이 재미 있을지 생각해 보았습니다. (그리고 나서 위키를 읽으십시오!)

"버스트"기능을 사용하려고하면 내 컴퓨터의 이상한 문제가 발생합니다. 귀하의 환경에서 재현 가능하다면, 앱을 실행하고 B를 치면 다시 생성 할 수 있습니다. 이것은 100 단계의 버스트가 발생하는 것으로 가정합니다 (즉, 100 개의 새로운 지침을 작성하고 버스트, 왜냐하면 콘솔에 쓰기가 너무 어색하게 느리다). 그러나 실제로는 단 하나의 단계로 끝납니다!

버스트 변수가 할당 된 ProcessKey()에 중단 점을 설정했습니다. 이 메소드에서 벗어나면 디버그 출력에서 ​​스레드가 종료되었음을 알 수 있습니다. 이것은 우연이 아닙니다. 매번 안정적으로 발생합니다. 그런 다음 내 시계는 이전 단계에서 1000에 할당 된 버스트 변수가 0임을 나타냅니다.

왜 이런 일이 발생합니까? 내가 뭐 잘못 했어요? STA를 지정하는 아무 속성도 없다는 것을 알았지 만 어쨌든 이러한 것들이 무엇인지 전혀 알지 못했고 사용 된 콘솔 응용 프로그램 템플릿에서 아무 것도 제거하지 않았습니다 (VS-2011 개발자 미리보기에서 Redmond I과 달리 2012 년 현재) ...

마지막으로 : 앱이 커서를 뒤로 이동하고 텍스트를 반복해서 덮어 씁니다. 한 번에 모든 출력을 표시 할 수있을만큼 콘솔 창을 충분히 높게 만들 수 없으면 콘솔 폰트를 사용하거나 콘솔의 너비를 변경해야 할 수도 있습니다. 나는 시험하지 않았다). 패턴은 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% 

이 의미 : 바이트 × 00이 특정 경우에 (509194 생성 된 모든 GUID를 각이 만들어 모든 바이트의 0.34 %를 0x3F입니다하기 위해,하지만 난이 결과 각을 얻을 내 HTPC에,이 결과를 얻을 수 10 만 명 이상의 가이드가있는 시간). 매우 다른 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 내 자신의 질문에 내 자신의 답변을 표시하지 못하게하기 때문에. (나는 그들의 "cred"시스템이 어쨌든 자신의 질문에 답하는 것을 무시한다고 생각해야한다. 왜이 정책이 적절한 지 모른다.) –