Когда и как я могу отменить регистрацию зарегистрированного пользователя - PullRequest
1 голос
/ 01 марта 2012

Я использую ThreadPool.UnsafeRegisterWaitForSingleObject (далее RWFSO) для асинхронного ожидания на Semaphore.Он возвращает мне RegisteredWaitHandle, что я не могу легко Unregister().Мне нужно отменить их регистрацию, потому что дескриптор хранит ссылку на делегат и его объект состояния, а мой процесс пропускает память с каждым дескриптором.В конце концов они завершаются, но это занимает слишком много времени и оказывает слишком большое давление на сборщик мусора, что приводит к увеличению использования личной памяти моего процесса в диапазоне 1,8 ГБ.Я делаю много асинхронных запросов.

Семафор используется для доступа к асинхронной реализации HttpWebRequest: BeginGetRequestStream и BeginGetResponse.Если я не использую семафор, он продолжает говорить мне «недостаточно свободных потоков в пуле потоков» из-за идиотского способа его реализации.Если я использую блокирующие примитивы, такие как semaphore.WaitOne(), тогда мой пул потоков будет в конечном итоге заблокирован, и ничего не произойдет.

RWFSO возвращает RegisteredWaitHandle, но это бесполезно для моего вызывающего потока, так как мне нужно Unregister()этот дескриптор только тогда, когда ожидание завершено;У меня нет сценария отмены.Я не могу просто передать экземпляр RegisteredWaitHandle своему делегату (через внешнее поле, установленное для объекта состояния, переданного делегату), потому что делегат может быть завершен в другом потоке до того, как управление даже вернется из RWFSO.

Как мне безопасно и быстро Unregister() a RegisteredWaitHandle с, когда и только когда его ожидание завершено?

Ответы [ 2 ]

2 голосов
/ 01 марта 2012

Просто передайте дескриптор делегату с помощью любого механизма, который вам подходит. Если к моменту выполнения делегата дескриптор равен нулю, делегат раскручивается при ожидании назначения. Не беспокойтесь о тривиальном количестве процессорного времени, потому что вы можете просто поместить Thread.Yield в цикл. Если это вас беспокоит, вы можете использовать замок.

В качестве альтернативы вы можете отменить регистрацию имеющихся там ручек и позволить GC убрать тех, кто проиграл гонку.

0 голосов
/ 01 марта 2012

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

...