Подтвердить что ты не робот

Thread.Sleep менее 1 миллисекунды

Я хочу назвать thread sleep менее 1 миллисекундой. Я читал, что ни thread.Sleep, ни Windows-OS не поддерживают это.

какое решение для этого?

Для всех, кто задается вопросом, зачем мне это нужно: Я делаю стресс-тест и хочу знать, сколько сообщений мой модуль может обрабатывать в секунду. Итак, мой код:

 // Set the relative part of Second hat will be allocated for each message 
 //For example: 5 messages - every message will get 200 miliseconds 
 var quantum = 1000 / numOfMessages;

 for (var i = 0; i < numOfMessages; i++)
 {
      _bus.Publish(new MyMessage());
      if (rate != 0) 
          Thread.Sleep(quantum);
 }

Я буду рад узнать ваше мнение об этом.

4b9b3361

Ответ 1

Вы не можете этого сделать. Один вызов сна обычно будет блокироваться намного дольше, чем миллисекунда (он зависит от ОС и системы, но, по моему опыту, Thread.Sleep(1) имеет тенденцию блокироваться где-то между 12-15 мс).

Windows, в общем, не разработана как операционная система в режиме реального времени. Обычно такого типа управления невозможно достичь на обычных (настольных/серверных) версиях Windows.

Самое близкое, что вы можете получить, - это, как правило, вращение и использование циклов процессора, пока вы не достигнете требуемого времени ожидания (измеренного с помощью высокопроизводительного счетчика). Это, однако, довольно ужасно - вы съедите целый процессор, и даже тогда вы, скорее всего, получите выгруженную операционной системой на раз и эффективно "спать" дольше 1 мс...

Ответ 2

Нижеприведенный код наиболее определенно предлагает более точный способ блокировки, а не вызов Thread.Sleep(x); (хотя этот метод будет блокировать поток, а не спать). Ниже мы используем класс StopWatch для определения того, как долго нам нужно продолжать цикл и блокировать вызывающий поток.

using System.Diagnostics;

private static void NOP(double durationSeconds)
{
    var durationTicks = Math.Round(durationSeconds * Stopwatch.Frequency);
    var sw = Stopwatch.StartNew();

    while (sw.ElapsedTicks < durationTicks)
    {

    }
}

Пример использования,

private static void Main()
{
    NOP(5); // Wait 5 seconds.

    Console.WriteLine("Hello World!");

    Console.ReadLine();
}

Ответ 3

Почему?
Обычно на одном компьютере имеется очень ограниченное количество процессоров и ядер - вы получаете только небольшое количество, если независимые исполнительные блоки.

С других рук есть несколько процессов и еще много потоков. Для каждого потока требуется некоторое время процессора, которое назначается внутренне с помощью основных процессов Windows. Обычно Windows блокирует все потоки и дает определенное количество времени ядра ядра конкретным потокам, затем переключает контекст на другие потоки.

Когда вы вызываете Thread.Sleep независимо от того, насколько малы, вы убиваете весь промежуток времени, который Windows предоставила для потока, так как нет причин просто ждать его, и контекст сразу переключается. Это может занять несколько мс, когда Windows в следующий раз даст вашему потоку некоторый процессор.

Что использовать?
Кроме того, вы можете вращать ваш процессор, вращение - это не страшная вещь, и это может быть очень полезно. Например, это часто используется в пространстве имен System.Collections.Concurrent с неблокирующими коллекциями, например:

SpinWait sw = new SpinWait();
sw.SpinOnce();

Ответ 4

Большинство законных причин использования Thread.Sleep(1) или Thread.Sleep(0) связаны с довольно продвинутыми технологиями синхронизации потоков. Как Рид сказал, вы не получите желаемого разрешения, используя обычные методы. Я не знаю точно, что именно вы пытаетесь выполнить, но я думаю, что могу предположить, что вы хотите вызвать действие в течение 1 миллисекунды. Если это так, взгляните на мультимедийные таймеры. Они могут обеспечить разрешение до 1 мс. К сожалению, нет API, встроенного в .NET Framework (что я знаю), который вписывается в эту функцию Windows. Но вы можете использовать слой interop для прямого вызова в API Win32. Есть даже примеры делать это на С# там.

Ответ 5

В старые добрые времена вы использовали бы API QueryPerformanceTimer для Win32, когда требовалось дополнительное разрешение в миллисекундах.

В Code-Project, по-видимому, больше информации по этому вопросу: http://www.codeproject.com/KB/cs/highperformancetimercshar.aspx

Это не позволит вам "Сон()" с тем же разрешением, что указано Ридом Копси.

Edit: Как указал Рид Копси и Брайан Гидеон, QueryPerfomanceTimer был заменен на Stopwatch в .NET

Ответ 6

Что касается принятого ответа Рида Копси, как насчет этого?

public void Sleep(double msec)
{
   for (var since = DateTime.Now; (DateTime.Now - since).TotalMilliseconds < msec;)
      Thread.Sleep(TimeSpan.FromTicks(10));
}