У меня была та же самая проблема не так давно, и если не использовать сторонние сервисы, то нет хороших способов обойти это.
Тем не менее, я использовал объект .NET Application Cache со сроком действия 24 часа.
Cache["DailyTask"] = true;
Затем в моем классе базовой страницы каждый раз, когда был сделан запрос страницы, я проверял наличие этой переменной и, если она существовала, запускал задачу. Недостатком этого является то, что в этом случае вы полагаетесь на запросы страниц, поданные в ваше приложение.
Наконец, еще один способ, которым я видел это, - установить обратный вызов по истечении срока действия кэша (метод CacheItemRemovedCallback), а затем связать этот метод для вставки нового элемента в кеш, который также имеет обратный вызов, и поэтому цикл повторяется.