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

Каково влияние Thread.Sleep(1) на С#?

В приложении формы Windows какое влияние вызывает вызов Thread.Sleep(1), как показано в следующем коде:

public Constructor()
{
    Thread thread = new Thread(Task);
    thread.IsBackground = true;
    thread.Start();
}

private void Task()
{
    while (true)
    {
        // do something
        Thread.Sleep(1);
    }
}

Будет ли этот поток запугать весь доступный CPU?

Какие методы профилирования я могу использовать для измерения этого использования процессора Thread (кроме диспетчера задач)?

4b9b3361

Ответ 1

Как уже говорилось, ваш цикл не будет обрабатывать CPU.

Но будьте осторожны: Windows - это не операционная система, поэтому вы не получаете 1000 запросов в секунду от Thread.Sleep(1). Если вы не использовали timeBeginPeriod, чтобы установить минимальное разрешение, вы будете просыпаться каждые 15 мс. Даже после того, как вы установили минимальное разрешение на 1 мс, вы все равно будете просыпаться каждые 3-4 мс.

Чтобы получить гранулярность таймера уровня миллисекунды, вы должны использовать мультимедийный таймер Win32 (С# wrapper).

Ответ 2

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

Ответ 3

Thread.Sleep(1), как указано, не будет обрабатывать CPU.

Вот что происходит, когда поток спит (более или менее):

  • Thread.Sleep транслируется в системный вызов, который, в свою очередь, запускает ловушку (прерывание, которое позволяет операционной системе принимать контроль)
  • Операционная система обнаруживает вызов в режиме сна и отмечает, что поток заблокирован.
  • Внутри ОС хранится список потоков, которые необходимо пробудить и когда это произойдет.
  • Поскольку поток больше не использует CPU, OS...
  • Если родительский процесс не исчерпал весь свой временной срез, ОС планирует запланировать еще один поток процесса для выполнения.
  • В противном случае начнется выполнение другого процесса (или незанятого процесса).
  • Когда время истечет, ваш поток будет снова запланирован для выполнения, что не означает, что он начнет выполнение автоматически.

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

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

Ответ 4

Как отметил Боб Надлер, Thread.Sleep(1) не гарантирует время сна 1 мс.

Вот пример использования мультимедийного таймера Win32, чтобы заставить спать 1 мс.

    [DllImport("winmm.dll")]
    internal static extern uint timeBeginPeriod(uint period);
    [DllImport("winmm.dll")]
    internal static extern uint timeEndPeriod(uint period);

    timeBeginPeriod(1);
    while(true)
    {
        Thread.Sleep(1); // will sleep 1ms every time
    }
    timeEndPeriod(1);

Проверяя это в приложении С# GUI, я обнаружил, что приложение использует около 50% моего процессора.

Подробнее об этом разделе см. в следующей теме:

http://www.dotnet247.com/247reference/msgs/57/289291.aspx

Ответ 5

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

Ответ 6

Это старый поток, который появляется во многих моих поисках, но Win7 имеет новый планировщик и, похоже, ведет себя иначе, чем выше.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime dtEnd = DateTime.Now.AddSeconds(1.0);
            int i = 0;
            while (DateTime.Now < dtEnd)
            {
                i++;
                Thread.Sleep(1);
            }

            Console.WriteLine(i.ToString());

            i = 0;
            long lStart = DateTime.Now.Ticks;
            while (i++ < 1000)
                Thread.Sleep(1);

            long lTmp = (DateTime.Now.Ticks - lStart) / 10000;

            Console.WriteLine(lTmp.ToString());

            Console.Read();
        }
    }
}

С приведенным выше кодом мой первый результат дал 946. Таким образом, в промежутке времени в 1 секунду, используя 1 мс, я получил 946 бодрствований. Это очень близко к 1 мс.

Вторая часть спрашивает, сколько времени занимает 1000 событий сна в 1 мс каждый. Я получил 1034 мс. Опять же, почти 1 мс.

Это было на 1.8ghz core2duo + Win7, используя .Net 4.0

Изменить: помните, sleep (x) не означает пробуждение в это время, это означает разбудить меня не раньше, чем на этот раз. Это не гарантировано. Хотя вы можете увеличить приоритет потока, и Windows должна запланировать ваш поток до потоков с более низким приоритетом.

Ответ 7

Нет, он не будет запугать весь доступный CPU, потому что спящий поток будет отключен планировщиком ОС, когда другой поток будет работать.

Ответ 8

Нет, не будет. Вы это почти не увидите. Где-то менее 1000 раз в секунду эта нить будет просыпаться и ничего не делать перед сном снова.

Изменить:

Мне нужно было проверить. Запуск на Java 1.5, этот тест

@Test
public void testSpeed() throws InterruptedException {
    long currentTime = System.currentTimeMillis();
    int i = 0;
        while (i < 1000)
        {
            Thread.sleep(1);
            i++;
        }
    System.out.println("Executed in " + (System.currentTimeMillis() - currentTime));
}

Ускорьте примерно на 500 спящих в секунду на моей машине 3ghz. Я полагаю, что С# должен быть примерно таким же. Я предполагаю, что кто-то отчитается с номерами С# для этого чрезвычайно важного эталона. Кстати, никакого наблюдаемого использования ЦП не наблюдалось.

Ответ 9

Нить может в любой момент запускать один (логический) процессор. И сон на 1 мс не будет болеть. Не потейте.

Ответ 10

также взгляните на это: msdn forum

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace Test
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();

            for (int i = 0; i < 10; ++i)
            {
                sw.Reset();
                sw.Start();
                Thread.Sleep(50);
                sw.Stop();

                Console.WriteLine("(default) Slept for " + sw.ElapsedMilliseconds);

                TimeBeginPeriod(1);
                sw.Reset();
                sw.Start();
                Thread.Sleep(50);
                sw.Stop();
                TimeEndPeriod(1);

                Console.WriteLine("(highres) Slept for " + sw.ElapsedMilliseconds + "\n");
            }
        }

        [DllImport("winmm.dll", EntryPoint="timeBeginPeriod", SetLastError=true)]
        private static extern uint TimeBeginPeriod(uint uMilliseconds);

        [DllImport("winmm.dll", EntryPoint="timeEndPeriod", SetLastError=true)]
        private static extern uint TimeEndPeriod(uint uMilliseconds);
    }
}