Насколько точен Thread.Sleep (TimeSpan)?

Алгоритм:

  • Подсчитайте от 1 до 2 ^ n.
  • Преобразуйте каждую цифру в ее двоичное представление.
  • бит в элементы вашего набора, в зависимости от положения.

В C #:

void Main()
{
    var set = new [] {"A", "B", "C", "D" }; //, "E", "F", "G", "H", "I", "J" };

    var kElement = 2;

    for(var i = 1; i < Math.Pow(2, set.Length); i++) {
        var result = Convert.ToString(i, 2).PadLeft(set.Length, '0');
        var cnt = Regex.Matches(Regex.Escape(result),  "1").Count; 
        if (cnt == kElement) {
            for(int j = 0; j < set.Length; j++)
                if ( Char.GetNumericValue(result[j]) == 1)
                    Console.Write(set[j]);
            Console.WriteLine();
        }
    }
}

Почему это работает?

биекция между подмножествами n-элементного множества и n-битовых последовательностей.

Это означает, что мы можем выяснить, сколько подмножеств существует путем подсчета последовательностей.

, например, четыре приведенных ниже элемента могут быть представлены {0,1} X {0, 1} X {0, 1} X {0, 1} (или 2 ^ 4) различными последовательностями.

Итак, все, что нам нужно сделать, это считать от 1 до 2 ^ n, чтобы найти все комбинации. (Мы игнорируем пустое множество.) Затем переведите цифры в их двоичное представление. Затем замените элементы вашего набора на биты «on».

Если вы хотите получить только результаты k-элемента, только распечатывайте, когда k бит «включено».

(Если вы хотите, чтобы все подмножества вместо подмножеств k длины удаляли часть cnt / kElement.)

(Для доказательства см. бесплатную учебную программу MIT Mathematics for Computer Science, Lehman et al. , раздел 11.2.2. https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-042j-mathematics-for-computer-science-fall-2010/readings/ )

16
задан mezoid 20 August 2009 в 03:45
поделиться

6 ответов

Ваш поток разделяет время ЦП с другими потоками. Спящий режим закончится, как только придет ваша очередь снова, и ядро ​​заметит, что время ожидания истекло, поэтому это не так точно.

Загрузка процессора, приоритеты процессов, количество параллельных потоков, даже от других процессов, будут иметь влияние на него.

15
ответ дан 30 November 2019 в 21:19
поделиться

Thread.Sleep не предназначен для точного пробуждения. На самом деле сама архитектура Windows не предназначена для такого рода вещей.

7
ответ дан 30 November 2019 в 21:19
поделиться

Спящий поток и синхронизация / регулирование - это разные вещи, и с ними следует обращаться соответствующим образом. Засыпание потока - это общая задача, позволяющая системе предоставить другим потокам и процессам возможность выполнения, не конкретизируя это. С другой стороны, регулирование приложения или планирование задач, требующих точного времени, следует выполнять с помощью явного таймера.

Имейте в виду, что если вам нужны процессы или синхронизация с точностью до времени, вам будет сложно добиться этого с помощью обычного процесса в Windows. Вам нужно будет использовать приоритеты Windows в реальном времени для успешного достижения точного времени или регулирования, так как окна могут в любое время засыпать любой поток, если его вытесняет другой поток.

2
ответ дан 30 November 2019 в 21:19
поделиться

В одном приложении, где я хотел спать по крайней мере на x миллисекунд, я использовал код, похожий на:

public void Sleep(int milliseconds)
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();

    while (stopwatch.ElapsedMilliseconds < milliseconds)
    {
        int timeout = milliseconds - stopwatch.ElapsedMilliseconds;
        Thread.Sleep(timeout >= 0 ? timeout : 0);
    }

    stopwatch.Stop();
}

В ответ на то, насколько точен Thread.Sleep, он совсем неточен. Думаю, разрешение где-то около 10мс. Не гарантируется, что он сделает что-либо, кроме «примерно» такого времени.

1
ответ дан 30 November 2019 в 21:19
поделиться

Может быть, вам не следует полагаться на временную предвзятость, чтобы узнать, где вы успешно. Лучше посчитайте количество попыток и сравните его с этим:

int tries;

for(tries=0; tries<3; tries++)
{
    Thread.Sleep(oneSecond);
}

Assert.GreaterOrEqual(tries, 3);
-1
ответ дан 30 November 2019 в 21:19
поделиться

Быстро экспериментируя, я заметил, что фрагмент кода вроде ...

do {Debug.WriteLine (DateTime.Now.TimeOfDay.TotalMilliseconds.ToString ()); } while (1);

отображает одно и то же число несколько раз, затем переходит к новому числу, отображаемому несколько раз, и т. д. Разрыв между этими наборами чисел постоянно составляет 15,625 мс, что, как я заметил, составляет 1000/64.

Похоже, таймеры Windows имеют дискретность 1/64 секунды. Если вам нужно что-то лучшее, я чувствую вашу боль, но это рамки, в которые вы должны вписаться. (Windows не является ОС реального времени и не претендует на нее).

3
ответ дан 30 November 2019 в 21:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: