Як змусити мою програму C # спати протягом 50 мілісекунд?
Це може здатися легким питанням, але у мене є момент тимчасової недостатності мозку!
Як змусити мою програму C # спати протягом 50 мілісекунд?
Це може здатися легким питанням, але у мене є момент тимчасової недостатності мозку!
Відповіді:
System.Threading.Thread.Sleep(50);
Пам'ятайте, що якщо це зробити в основному потоці графічного інтерфейсу, блокує оновлення вашого графічного інтерфейсу (він буде відчувати себе "млявим")
Просто видаліть, ;
щоб він працював і для VB.net.
В основному є 3 варіанти очікування (майже) будь-якої мови програмування:
для 1. - Вільне очікування в C #:
Thread.Sleep(numberOfMilliseconds);
Однак планувальник потоків Windows спричиняє накопичення Sleep()
близько 15 мс (тому сон може легко чекати 20 мс, навіть якщо планується чекати лише 1 мс).
для 2. - Тісне очікування в C # - це:
Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
//some other processing to do possible
if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
{
break;
}
}
Ми також могли використовувати DateTime.Now
або інші засоби вимірювання часу, але Stopwatch
це набагато швидше (і це дійсно стане видно в тісному циклі).
для 3. - Поєднання:
Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
//some other processing to do STILL POSSIBLE
if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
{
break;
}
Thread.Sleep(1); //so processor can rest for a while
}
Цей код регулярно блокує потік на 1 мс (або трохи більше, залежно від планування потоку ОС), тому процесор не зайнятий на той час блокування, і код не споживає 100% потужності процесора. Інша обробка все ще може бути виконана між блокуванням (наприклад: оновлення інтерфейсу користувача, обробка подій або взаємодія / спілкування).
Ви не можете вказати точний час сну в Windows. Для цього вам потрібна ОС у режимі реального часу. Найкраще, що ви можете зробити, це вказати мінімальний час сну. Тоді до планувальника варто прокинути свою нитку після цього. І ніколи не дзвоніть .Sleep()
на нитку GUI.
Оскільки тепер у вас є функція асинхронізації / очікування, найкращий спосіб спати протягом 50 мс - це за допомогою Task.Delay:
async void foo()
{
// something
await Task.Delay(50);
}
Або якщо ви орієнтуєтесь на .NET 4 (з Async CTP 3 для VS2010 або Microsoft.Bcl.Async), ви повинні використовувати:
async void foo()
{
// something
await TaskEx.Delay(50);
}
Таким чином, ви не будете блокувати потік інтерфейсу користувача.
FlushAsync
версія.
async
декларації, - зателефонуватиTask.Delay(50).Wait();
Використовуйте цей код
using System.Threading;
// ...
Thread.Sleep(50);
Thread.Sleep(50);
Потік не планується виконувати операційною системою протягом зазначеного часу. Цей метод змінює стан потоку, щоб включити WaitSleepJoin.
Цей метод не виконує стандартних перекачування COM та SendMessage. Якщо вам потрібно спати на потоці, у якому є STAThreadAttribute, але ви хочете виконати стандартну перекачку COM і SendMessage, подумайте про використання одного з перевантажень методу Join, який визначає інтервал очікування.
Thread.Join
Для читабельності:
using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
Кращі з обох світів:
using System.Runtime.InteropServices;
[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);
/**
* Extremely accurate sleep is needed here to maintain performance so system resolution time is increased
*/
private void accurateSleep(int milliseconds)
{
//Increase timer resolution from 20 miliseconds to 1 milisecond
TimeBeginPeriod(1);
Stopwatch stopwatch = new Stopwatch();//Makes use of QueryPerformanceCounter WIN32 API
stopwatch.Start();
while (stopwatch.ElapsedMilliseconds < milliseconds)
{
//So we don't burn cpu cycles
if ((milliseconds - stopwatch.ElapsedMilliseconds) > 20)
{
Thread.Sleep(5);
}
else
{
Thread.Sleep(1);
}
}
stopwatch.Stop();
//Set it back to normal.
TimeEndPeriod(1);
}