Приостановка метода для набора из миллисекунд

Мне нужно сделать своего рода "тайм-аут" или приостановить мой метод в течение 10 секунд (10000 миллисекунд), но я не уверен, что следующее будет работать, поскольку у меня нет многопоточности.

Thread.Sleep(10000);

Я попытаюсь использовать этот текущий код, но я был бы признателен, если бы кто-нибудь мог объяснить лучший и правильный способ сделать это, особенно если вышеуказанный код не работает должным образом. Спасибо!

UPDATE. Эта программа на самом деле является консольным приложением, которое в рассматриваемой функции делает много HTTPWebRequests на одном сервере, поэтому я хочу задержать их на заданное количество миллисекунд. Таким образом, обратный вызов не требуется - все, что требуется, - это "безусловная пауза" - в основном, все это останавливается на 10 секунд, а затем продолжает идти. Я рад, что С# все еще считает это потоком, поэтому Thread.Sleep(...) будет работать. Спасибо всем!

Ответ 1

У вас может не быть многопоточности, но вы все еще выполняете в потоке: весь код выполняется в потоке.

Вызов Thread.Sleep действительно приостановит текущий поток. Вы действительно хотите, чтобы он безоговорочно остановился на 10 секунд или вы хотите быть "проснувшимся" от чего-то еще? Если вы используете только один поток, вызов Sleep может быть лучшим способом продвижения вперед, но он будет зависеть от ситуации.

В частности, если вы пишете графическое приложение, вы не хотите использовать Thread.Sleep из потока пользовательского интерфейса, так как в противном случае все ваше приложение перестанет отвечать на запросы в течение 10 секунд.

Если вы могли бы предоставить больше информации о своем приложении, это поможет нам лучше советовать.

Ответ 2

Это действительно приостановит выполнение потока/метода в течение 10 секунд. Вы видите конкретную проблему?

Обратите внимание, что вы не должны Sleep поток пользовательского интерфейса - лучше было бы сделать обратный вызов.

Обратите также внимание на то, что есть другие способы блокировки потока, которые позволяют более простой доступ для его повторения (если вы обнаружите, что это нормально после 2 секунд); например Monitor.Wait(obj, 10000) (если для его пробуждения требуется другой поток Pulse):

static void Main() {
    object lockObj = new object();
    lock (lockObj) {
        new Thread(GetInput).Start(lockObj);
        Monitor.Wait(lockObj, 10000);
    }
    Console.WriteLine("Main exiting");
}
static void GetInput(object state) {
    Console.WriteLine("press return...");
    string s = Console.ReadLine();
    lock (state) {
        Monitor.Pulse(state);
    }
    Console.WriteLine("GetInput exiting");
}

Вы можете сделать это с помощью Thread.Interrupt тоже, но IMO, который более беспорядочен.

Ответ 3

Для этого можно использовать отдельный поток:

   ThreadPool.QueueUserWorkItem(
       delegate(object state)
       {
           Thread.Sleep(1000);
           Console.WriteLine("done");
       });

Но если это приложение Windows Forms, вам нужно будет вызвать код после задержки из потока Gui (эта статья, например: Как обновить графический интерфейс из другого потока в С#?).

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

Если вам не нужны фоновые работники, придерживайтесь "упрощения".

Ответ 4

Thread.Sleep в порядке, и AFAIK правильный путь. Даже если вы не многопоточны: всегда есть хотя бы один поток, и если вы отправляете его спать, он спит.

Другой (плохой) способ является спин-блокировкой, что-то вроде:

// Do never ever use this
private void DoNothing(){ }

private void KillCPU()
{
    DateTime target = DateTime.Now.AddSeconds(10);
    while(DateTime.Now < target) DoNothing();
    DoStuffAfterWaiting10Seconds();
}

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

Ответ 5

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

public class PauseClass
{
    //(C) Michael Roberg
    //Please feel free to distribute this class but include my credentials.

    System.Timers.Timer pauseTimer = null;

    public void BreakPause()
    {
        if (pauseTimer != null)
        {
            pauseTimer.Stop();
            pauseTimer.Enabled = false;
        }    
    }

    public bool Pause(int miliseconds)
    {
        ThreadPriority CurrentPriority = Thread.CurrentThread.Priority;

        if (miliseconds > 0)
        {
            Thread.CurrentThread.Priority = ThreadPriority.Lowest;

            pauseTimer = new System.Timers.Timer();
            pauseTimer.Elapsed += new ElapsedEventHandler(pauseTimer_Elapsed);

            pauseTimer.Interval = miliseconds;
            pauseTimer.Enabled = true;

            while (pauseTimer.Enabled)
            {
                Thread.Sleep(10);
                Application.DoEvents();
                //pausThread.Sleep(1);
            }

            pauseTimer.Elapsed -= new ElapsedEventHandler(pauseTimer_Elapsed);
        }

        Thread.CurrentThread.Priority = CurrentPriority;

        return true;
    }

    private void pauseTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        pauseTimer.Enabled = false;
    }
}

Ответ 6

Да, это работает нормально.

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

Ответ 7

Для тайм-аута вы должны иметь статическое поле volatile boolean isRunning. Когда начинается новый поток, isRunning должен стать истинным, а в конце должен стать false.

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

Пауза... нет простого решения. Это зависит от того, что вы делаете внутри потока. Однако вы можете посмотреть Monitor.Wait.