Сообщите, что выполняется длительная асинхронная задача - правильный путь - PullRequest
0 голосов
/ 05 ноября 2018

У меня есть консольная программа, которая отправляет асинхронные HTTP-запросы на внешний веб-API. (HttpClient.GetAsync());)
Выполнение этих задач может занять несколько минут, в течение которых я хотел бы показать пользователю, что приложение все еще работает, например, отправляя Console.WriteLine("I ain't dead - yet") каждые 10 секунд.

Я не уверен, как это сделать правильно, без риска скрыть исключения, ввести взаимоблокировки и т. Д.

Мне известен IProgress , однако я не знаю, смогу ли я представить его в этом случае. Я жду одного асинхронного вызова, который не сообщает о прогрессе. (По сути, это SDK, который вызывает метод httpClient GetAsync ()

Также: Я не могу установить графический интерфейс на «InProgress», потому что нет графического интерфейса, это консольное приложение - и пользователю кажется, что он перестал работать, если я не время от времени отправляю сообщение об обновлении.

Текущая идея:

            try
            {
                var task = httpClient.GetAsync(uri); //actually this is an SDK method call (which I cannot control and which does not report progress itself)

                while (!task.IsCompleted)
                {
                    await Task.Delay(1000 * 10);
                    this.Logger.Log(Verbosity.Verbose, "Waiting for reply...");
                }
                onSuccessCallback(task.Result);
            }
            catch (Exception ex)
            {
                if (onErrorCallback == null)
                {
                    throw this.Logger.Error(this.GetProperException(ex, caller));
                }
                this.Logger.Log(Verbosity.Error, $"An error when executing command [{action?.Command}] on {typeof(T).Name}", ex);
                onErrorCallback(this.GetProperException(ex, caller));
            }

1 Ответ

0 голосов
/ 05 ноября 2018

Позвольте мне немного привести в порядок этот код для вас

async Task Main()
{
    var reporter = new ConsoleProgress();
    var result = await WeatherWaxProgressWrapper(() => GetAsync("foo"), reporter);

    Console.WriteLine(result);
}



public async Task<int> GetAsync(string uri)
{
    await Task.Delay(TimeSpan.FromSeconds(10));
    return 1;
}

public async Task<T> WeatherWaxProgressWrapper<T>(Func<Task<T>> method, System.IProgress<string> progress)
{
    var task = method();
    while(!task.IsCompleted && !task.IsCanceled && !task.IsFaulted)
    {
        await Task.WhenAny(task, Task.Delay(1000));
        progress.Report("I ain't dead");
    }
    return await task;
}

public class ConsoleProgress : System.IProgress<string>
{
    public void Report(string value)
    {
        Console.WriteLine(value);
    }
}
...