Вопрос по thread-sleep, async-await, task-parallel-library, .net, c# – Должен ли я всегда использовать Task.Delay вместо Thread.Sleep? [Дубликат]

4

На этот вопрос уже есть ответ здесь:

Когда использовать Task.Delay, когда использовать Thread.Sleep? 4 ответа

Недавно я видел несколько рекомендаций о том, чтоThread.Sleep никогда не должен использоваться в производственном коде (последний раз вэтот ТАК вопрос). Многие из них выступают за использованиеTask.Delay вместо. В большинстве объяснений, которые я нашел, в качестве примеров используются приложения пользовательского интерфейса, посколькуTask.Delay очевидны (не блокируют пользовательский интерфейс).

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

DateTime end = DateTime.UtcNow + TimeSpan.FromMinutes(2);
while (DateTime.UtcNow < end)
{
    if (ExternalServiceIsReady() == true)
    {
        return true;
    }
    Thread.Sleep(1000);
}

В этом случае следующие потенциальные преимуществаTask.Delay кажется, не применяются:

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

Это тот случай, когда целесообразно использоватьThread.Sleep? Каково было бы преимущество (если есть) замены линии сна наTask.Delay(1000).Wait()?

Нет петли, нет нити, нет сна. Hans Passant
Трудно понять, почему вы подняли это, вы уже решили не использовать его. Hans Passant
@ HansPassant Не могли бы вы рассказать, почему Таймер является лучшим решением? BJ Myers
Есть ли опция C для использования события? Это может быть более подходящим, чем этот подход к опросу. Jeroen Vannevel

Ваш Ответ

1   ответ
7

Thread.Sleep(1000); вTask.Delay(1000).Wait();, Если вы хотите ждать синхронно, просто используйтеThread.Sleep.

Если у вас действительно есть только один поток и вы планируете сохранить его таким образом, тогда вы можете использоватьThread.Sleep, Тем не менее, я бы все равно использовалTask.Delay как это предпочтительнее в большинстве случаев, и поэтому это хороший шаблон. Я бы блокировал только на самом верху, когда ты не можешь использоватьasync больше, и даже тогда я бы предложил использовать какой-тоAsyncContext.

Вы также можете использоватьSystem.Threading.Timer непосредственно* вместоTask.Delay однако вы должны иметь в виду, что таймер выполняется каждый интервал и не ожидает завершения фактической операции, поэтому еслиExternalServiceIsReady занимает больше, чем интервал, вы можете иметь несколько вызовов к этой услуге одновременно.

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

await ExternalServiceIsReadyAsync();

* Task.Delay используетSystem.Threading.Timer внутри, который также имеет разрешение ~ 15 мс.

@SriramSakthivelThread.Sleep (как иTask.Delay) не тратит циклы процессора. Это постоянный опрос и одиночная асинхронная операция (будь тоasync или иначе) решает это. i3arnon
@EZI Асинхронная операция означает, что она уведомляет вас о завершении. Неважно, если это сделано, конкурируяTaskвызывая обратный вызов или вызывая событие. Это все то же самое и может быть преобразовано в другие методы. i3arnon
@EZI Замена цикла синхронной блокировки на асинхронный ожидаемый вызов будет означать потерю одного потока (и его циклов ЦП). i3arnon
@ i3arnon Я знаю, что такое асинхронная операция, но, похоже, вы не понимаете ее использование. Замена этой строкиawait ExternalServiceIsReadyAsync(); не изменил бы ничего EZI

Похожие вопросы