В чем причина использования Thread.Sleep в многопоточных приложениях? - PullRequest
3 голосов
/ 29 марта 2011

Часто, когда я вижу какой-нибудь многопоточный код, я вижу в коде Thread.Sleep() операторы.

У меня даже случался сбой, когда я пытался выяснить проблему, поэтому прокомментировал большинствоиз многопоточного кода и медленно принес его и для последней части, когда я добавил оператор for, как:

for ( int i = 0; i < 1000000; ++i )
    ++i;

он не вылетел.Так что теперь я заменил его Thread.Sleep(), и, похоже, работает.Я не могу легко воспроизвести его, чтобы опубликовать его здесь, но использует ли Thread.Sleep() необходимое для многопоточных приложений?

Какова их цель?Приведет ли это к неожиданным результатам, если не использовать?

РЕДАКТИРОВАТЬ: Кстати, я использую BackgroundWorker и только реализую свои вещи там, но не уверен, что это вызывает.Хотя я использую API, который является приложением хостинга, где приложение не является многопоточным.Так, например, я думаю, что не могу вызывать его функции API в нескольких потоках одновременно.Не уверен, но это было мое предположение.

Ответы [ 5 ]

6 голосов
/ 29 марта 2011

Как правило, Thread.Sleep является признаком плохого дизайна.При этом, он НАМНОГО лучше, чем потребляет 100% времени ядра ЦП, что и делает цикл выше.

Лучшим вариантом, как правило, является использование WaitHandle, например * 1005.*, чтобы инициировать продолжение выполнения потока, когда происходит «событие» (которое является причиной задержки).Кроме того, использование Timer может также работать во многих случаях.

3 голосов
/ 29 марта 2011

Thread.Sleep(1) позволяет переключиться на выполнение другого потока. Так что, если у вас больше потоков, чем ядер / процессоров, и вы знаете, что «сейчас я проделал в этом потоке много работы, а следующую работу можно сделать чуть позже», вы вызываете Thread.Sleep(1) и позволяете другому потоку выполнить некоторую работу раньше, чем нативный переключатель будет «приостанавливать» текущий исполняемый поток.

1 голос
/ 30 марта 2011

Thread.Sleep() можно использовать в некоторых ситуациях, например. сторожевые темы.

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

Без примера кода трудно сказать, но, исходя из вашего описания, я не думаю, что это вопрос Thread.Sleep() или нет. Я подозреваю, что вы можете страдать от состояния гонки - именно поэтому вы испытываете «случайное» ошибочное поведение или даже «случайные» сбои в многопоточном коде - как кажется, то, что вы испытываете.

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

Я рекомендую прочитать http://www.amazon.com/Concurrent-Programming-Windows-Joe-Duffy/dp/032143482X

1 голос
/ 29 марта 2011

Thread.Sleep() просто приводит к остановке исполняющего потока на указанную продолжительность.

Я видел, как многие разработчики используют Thread.Sleep(), потому что они, вероятно, не обрабатывают присоединение зависимых потоков.Они просто используют Thread.Sleep(), чтобы заставить поток ждать некоторое время, пока другие его потоки не закончили бы и не получили свои данные.

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

1 голос
/ 29 марта 2011

Попробуйте: напишите программу, которая запускает 100 потоков, и поместите каждый поток в цикл for, как вы описали.А затем напишите другой, который запускает 100 потоков и использует Thread.Sleep.

Запустите их оба и сравните загрузку ЦП.Вы увидите смысл.=)

...