Как бесконечно запускать асинхронные задачи, используя таймер с разными сделками

Я работаю над консольным приложением. Я организовал общие операции в задачах. Каждая задача (например, задача 1, задача 2, задача 3) должна выполняться неограниченное время в зависимости от собственной задержки (например, задача 1 каждые 5 минут, задача 2 каждый час и задача 3 один раз в день). Когда пользователь закрывает приложение, оно должно дождаться завершения всех запущенных задач, а все ожидающие должны быть отменены. Проблема в том, что я не знаю, как это сделать правильно. Я попробовал что-то вроде приведенного ниже кода, но основной процесс существует, как только он достигает строки t1.Start(). Это ожидаемое поведение, но я совершенно не знаю, как действовать дальше.

class Program
{
    static void Main(string[] args)
    {
        string path = @"config.json";
        Config config = ConfigParser.Parse(path);

        TimerTask t1 = new TimerTask(async () => await Task1(config), 300000);
        t1.Start();
    }
}

private static async Task Task1(Config config)
{
    // read from a database
    // call external service
    // write to the database
}    

public class TimerTask
{
    private readonly Timer taskTimer;

    public TimerTask(Action action, int interval = 10000)
    {
        taskTimer = new Timer { AutoReset = true, Interval = interval };
        taskTimer.Elapsed += (_, __) => action();
    }

    public void Start() { taskTimer.Start(); }

    public void Stop() { taskTimer.Stop(); }
}

person janas    schedule 29.03.2017    source источник
comment
Я думаю, вам просто нужен Console.ReadKey, чтобы ваша программа не завершилась, пока пользователь не нажмет клавишу или что-то в этом роде.   -  person BradleyDotNET    schedule 30.03.2017
comment
Итак, подождите после вызова метода Start? Вы можете спросить и дождаться ввода пользователя, таким образом, он не выйдет после t1.Start. Самый простой способ сделать это - просто использовать Console.Read()   -  person Selman Genç    schedule 30.03.2017
comment
Непонятно, как вы ожидаете завершения своей задачи, но помеченный дубликат объясняет, как вы можете ждать, пока это произойдет. Что касается самих таймеров, я бы не стал использовать класс Timer. Поскольку вы все равно используете объекты Task, вы должны писать свои прерывистые задачи как методы async, используя Task.Delay(), и вы можете WaitAll() задачи, как только вы сделали все, что вам нужно сделать, чтобы дать им сигнал прекратить выполнение.   -  person Peter Duniho    schedule 30.03.2017
comment
@Selman Genç Я знаю об этом, но затем приложение закрывается, как только нажимается любая клавиша. И любая запущенная задача прерывается, а это не то, что я ищу. Запущенные задачи должны быть завершены до завершения основного процесса.   -  person janas    schedule 30.03.2017