2009-07-01 3 views
10

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

Thread.Sleep(10000); 

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

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

+0

Это приложение Windows Forms? – Groo

+0

Я обновил сообщение, чтобы уточнить характер приложения. –

ответ

12

Возможно, у вас нет multi -понимание, но вы все еще выполняете в потоке: весь код выполняется в потоке.

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

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

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

+1

Мое приложение на самом деле является консольным приложением, которое производит огромное количество HTTP-запросов на один сервер, поэтому я не хочу его подавлять и приостанавливать между партиями 4 или около того, которые уже автоматически приостанавливаются, но без такого кода. Да, я надеялся, что C# все еще признает это как нить, поэтому спасибо! –

1

Да, это работает отлично.

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

3

Это действительно приостановит выполнение потока/метода в течение 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 тоже, но ИМО это хаотичным.

+0

Спасибо за советы! –

0

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

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

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

1

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

Другой (плохо) способ is a spinlock, что-то вроде:

// 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% использование CPU (Ну, на многоядерных системах это одно ядро).

+0

Im laffing на примере процессора - это нужно будет записать в моей книге как классический способ заполнить чей-то процессор! : D спасибо за подсказку tho! –

+1

'while (DateTime.Now Groo

+0

К счастью, я только нубошь в терминах потокования и всего этого хорошего материала - {} я понимаю tho. : D –

2

Вы можете использовать отдельный поток, чтобы сделать это:

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

Но, если это приложение под управлением Windows Forms, вам нужно будет вызывать код после задержки из нити Gui (эта статья , например: How to update the GUI from another thread in C#?).

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

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

2

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

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; 
    } 
} 
Смежные вопросы