Создание многопоточности для функции с ожиданием

Есть некая функция, выполняющая отправку сообщений с задержкой, используя авторизационный код, сообщение, и временная задержка между сообщениями, подготовленные определенным пользователем.

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

Сначала для решения этой задачи я создал такой код, который делает что-то похожее на то что я хочу сделать:

bool IsPosting = true;
var task = Post();


await task;
static async Task Post()
    
{
    while(IsPosting) {
        Console.WriteLine("Отправка сообщения");

        await Task.Delay(5000); 

       
    }
    
}

Но будет если такой код работать корректно, если запустить таким образом 1000+ задач ? Как можно реализовать это более лучшим способом ?


Ответы (1 шт):

Автор решения: Швеев Алексей

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

В итоге получается примерно такой класс:

class MessageSenderTask
{
    // Сурс для получения токена для отмены задачи
    CancellationTokenSource cts = new();

    // Сообщение, которое мы отправляем
    public string Message = "";

    // Задержка между сообщениями (static потому что она едина для всех)
    public static int Delay = 1000;

    // Отменить задачу
    public void Cancel() => cts.Cancel();

    void SendMessage(string message) =>
        Console.WriteLine(message);

    // Создаём задачу
    Task makeTask(CancellationToken cancellationToken) => new Task(async () =>
    {
        try
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                SendMessage(Message);
                await Task.Delay(Delay, cancellationToken);
            }
        }
        catch (TaskCanceledException) { }
    }, cancellationToken);

    // Создаём запущенную задачу
    public void Start() => makeTask(cts.Token).Start();
}

Пример использования:

var task1 = new MessageSenderTask() { Message = "Hello from task1" };
var task2 = new MessageSenderTask() { Message = "Hello from task2" };

Task.Delay(1000).Wait();

task1.Start();
task2.Start();

Task.Delay(5000).Wait();

task1.Cancel();

task2.Message = "new message";

Task.Delay(5000).Wait();

task2.Cancel();
→ Ссылка