Прошу комментарий к Await / Async

Рейтинг: 0Ответов: 1Опубликовано: 07.04.2023

Всем примет. Прошу совета, верно ли делаю относительно своих комментариев. И возможные исправления в по части последовательности выполнения кода.

{
    var history = await _historyService.GetHistory(_id); // ---- Долгая, но данные нужны уже тут, потому просто жду.
    var resultTask = _httpService.RunWithHistoryAsync(history, (int)_id); //---- Долгая, Выполняю в фоне.
    SendStopButton(_id);
    SetActivity(_id);
    var historyTask = _historyService.GetHistory(_id); - история изменилась, но данные нужны позже, выполняю в фоне.
    
    while (!resultTask.IsCompleted) //---- Нужно, иначе перестает показывать прелоад ( что юзер пишет в чат). Он настроен на 3сек, код выплоняеться дольше.
    {
        await Task.Delay(TimeSpan.FromSeconds(0.5));
        SetActivity(_id); //---- сам прелоад
    }
    var result = await resultTask; //---- не жду в методе  SendMessage, тк необходимо максимально сократить время между удалением и новым сообщением. Иначе может выйти так, что historyTask готов и удаление сработает, а result еще не готов и между этими методами пройдет вечность.
    MessageDelite(_id, await historyTask); //---- Удаляю последнее сообщение
    SendMessage(_id, result); //---- максимально быстро отправляю после удаления
     
    return;
};
  1. например Task<List<MessageInfo>> historyTask = Task.Run(() => _historyService.GetHistory(_id)); и потом ожидание, равносильно var historyTask = _historyService.GetHistory(_id); и потом ожидание
  2. Что-то можно улучшить? Я понимаю, что код короткий, но не уверен что делаю лучшим образом эту часть, тк учусь. Спасибо

Ответы

▲ 2Принят

Нет смысла в Task.Run, если вы работаете с асинхронной операцией.

Можно например вынести поллинг в отдельный метод и останавливать его токеном отмены.

private async Task HeartbeatAsync(int id, CancellationToken token)
{
    try
    {
        while (true)
        {
            SetActivity(id);
            await Task.Delay(TimeSpan.FromSeconds(0.5), token);
        }
    }
    catch (OperationCanceledException)
    { }
}

Тогда получится вот так

using CancellationTokenSource cts = new();
Task preload = HeartbeatAsync(_id, cts.Token);
try
{
    var history = await _historyService.GetHistory(_id);
    var resultTask = _httpService.RunWithHistoryAsync(history, (int)_id);
    SendStopButton(_id);
    var historyResult = await _historyService.GetHistory(_id);
    var result = await resultTask;
    MessageDelite(_id, historyResult); // не Delite, в Delete пишется
    SendMessage(_id, result);
}
finally
{
    cts.Cancel();
}
await preload;

Возможно еще что-то можно оптимизировать, возможно от цикла можно избавиться, но вы не показали что из себя представляют вызываемые методы и какими типами данных они оперируют, особенно SetActivity (при чем тут 3 секунды и т.д.).