1. Кучу памяти сжирает change tracker в EF, так что первым шагом его отключаем, добавляя AsNoTracking к каждому запросу.
А там где действительно нужно отcлеживать изменения - отсоединяем объекты, когда они не нужны при помощи Detach
2. Включаем ServerGarbageCollection, чтобы сборщик мусора мог работать в несколько потоков
3. Заменяем синхронные вызовы EF на асинхронные.
По идее тоже должно немного помочь
4. Вытаскиваем объекты из базы не по одному, а пачками штук по 100, тк GC проще работать с большими кусками, чем с маленькими
5. Если я правильно понимаю, это у вас HostedService.
В таком, случае смотрите внимательно на использование контекста, тк ещё в другом месте может Change Tracker нагружаться