Редактировать: После получения пяти отрицательных голосов, но без комментариев, говорящих о том, почему, я попытался переформулировать вопрос. Я могу только предположить, что голоса были, потому что люди видят много текста и, возможно, думают, что здесь даже нет вопроса.
Я написал код, который (неправильно) ведет себя довольно странно. Кажется, код не работает так же на других компьютерах, поэтому, пожалуйста, не сердитесь на меня, если вы не можете воспроизвести проблему.
Я просто для интереса посмотрел на частоты, с которыми в GUID встречаются разные байты. Я заметил, что строковые представления направляющих всегда содержали «4». Вместо того, чтобы читать об этом в Википедии, я попытался подумать о том, что это может быть, так как может быть интересно провести небольшое «оригинальное исследование» и время от времени думать самостоятельно. (А потом прочитайте вики!)
Странная проблема на моей машине возникает, когда я пытаюсь использовать функцию "Взрыв". Если это воспроизводимо в вашей среде, вы можете воссоздать его, запустив приложение и нажав 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
}
}