QueueUserAPC
- это аккуратный инструмент, который часто может быть ярлыком для некоторых задач, которые иначе обрабатываются объектами синхронизации. Он позволяет вам указывать конкретному потоку делать что-то, когда это удобно для этого потока (т.е. когда он заканчивает свою текущую работу и начинает что-то ожидать).
Допустим, у вас есть основной поток и рабочий поток. Рабочий поток открывает сокет для файлового сервера и начинает загрузку файла объемом 10 ГБ, вызывая recv () в цикле. Основной поток хочет, чтобы рабочий поток делал что-то еще во время простоя, пока он ожидает сетевых пакетов; он может поставить в очередь функцию, которая будет выполняться на рабочем месте, в то время как в противном случае он будет ждать и ничего не делать.
Вы должны быть осторожны с APC, потому что, как в упомянутом выше сценарии, вы не захотите сделать еще один блокирующий вызов WinSock (что приведет к неопределенному поведению). Вы действительно должны наблюдать, чтобы найти какое-либо хорошее использование этой функциональности, потому что вы можете сделать то же самое другими способами. Например, имея другой поток, проверяющий событие каждый раз, когда он собирается перейти в спящий режим, вместо того, чтобы дать ему функцию для запуска, пока он ожидает. Очевидно, что в этом случае APC будет проще.
Это похоже на то, что когда сотрудник телефонной станции сидит и ждет телефонных звонков, и вы даете этому человеку небольшие задачи во время простоя. «Вот, решите кубик Рубика, пока вы ждете». Хотя при поступлении телефонного звонка человек не откладывает кубик Рубика, чтобы ответить на звонок (БТР должен вернуться, прежде чем поток сможет вернуться к ожиданию).
QueueUserAPC
также полезно, если существует один поток (Поток A), который отвечает за некоторую структуру данных, и вы хотите выполнить некоторую операцию над структурой данных из другого потока (Поток B), но вы не делаете не нужно иметь накладные расходы на синхронизацию / сложность при попытке разделить эти данные между двумя потоками. Имея в потоке B очередь операцию, выполняемую в потоке A, который поддерживает только эту структуру, вы выполняете любую произвольную функцию для этих данных, не беспокоясь о синхронизации.
Это просто еще один инструмент, такой как пул потоков. Однако с пулом потоков вы не можете отправить задачу определенному потоку. Вы не можете контролировать, где выполняется работа. Когда вы ставите в очередь задачу, которая может закончиться созданием целого нового потока. Вы можете поставить в очередь две задачи, и они выполняются одновременно в двух разных потоках. С QueueUserAPC
вы можете быть уверены, что задачи будут выполнены в указанном порядке и в указанном вами потоке.