Асинхронный метод с асинхронным лямбда-выражением - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть лямбда-выражение с асинхронным вызовом внутри

public async Task UploadFile(string id)
{
    Progress<double> progress = new Progress<double>(async x =>
    {
        await Clients.Client(id).SendAsync("FTPUploadProgress", x);
    });
    await client.DownloadFileAsync(localPath, remotePath, true, FluentFTP.FtpVerify.Retry, progress);
}

Я хочу вызвать асинхронный метод, когда прогресс изменяется.

Я получаюследующее предупреждение:

В этом асинхронном методе отсутствуют операторы ожидания и он будет работать синхронно.Попробуйте использовать оператор 'await' для ожидания неблокирующего вызова API

Как сделать этот метод асинхронным?

Должен ли я переписать лямбду с классом System.Action<T>?

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Используйте обработчик событий и поднимите его в действии прогресса.обработчик событий разрешит асинхронные вызовы.

К счастью Progress<T> имеет событие ProgressChanged, на которое вы можете подписаться.

Просмотрите следующий пример на основе представленного кода в исходной задаче

public async Task UploadFile(string id) {
    EventHandler<double> handler = null;
    //creating the handler inline for compactness
    handler = async (sender, value) => {
        //send message to client asynchronously
        await Clients.Client(id).SendAsync("FTPUploadProgress", value);
    };
    var progress = new Progress<double>();
    progress.ProgressChanged += handler;//subscribe to ProgressChanged event

    //use the progress as you normally would
    await client.DownloadFileAsync(localPath, remotePath, true, FluentFTP.FtpVerify.Retry, progress);

    //unsubscribe when done 
    progress.ProgressChanged -= handler;
}

Так что теперь, когда сообщается о прогрессе, обработчик событий может выполнить асинхронный вызов.

Ссылка Асинхронное / ожидание - Рекомендации по асинхронному программированию

Другой вариант - создать собственную реализацию IProgress<T>, которая принимает Func<Task<T>>, которая допускает асинхронные вызовы, но это может быть излишним.

0 голосов
/ 21 сентября 2018

Я думаю, вы неправильно поняли использование класса Progress<T>.Компилятор жалуется, что в вашем методе UploadFile отсутствует оператор await.Ваша лямбда будет выполняться асинхронно, когда она будет вызываться.

Итак, вот краткое резюме, как использовать интерфейс IProgressyT>:

Если у вас есть метод, который должен поддерживать создание отчетов о прогрессе, он может принять IProgress<T> в качестве параметра и сообщитьего porgress через этот объект. не не выполняет контролируемую операцию.Лямбда, которую вы предоставляете, выполняется каждый раз, когда метод Report() вызывается на Progress<T>.Эта лямбда обычно используется для обновления пользовательского интерфейса.

Вот пример для этого.

public async Task DoStuff(IProgress<double> progress = null)
{
     for(int i = 0; i < 100; ++i)
     {
         await Task.Delay(500);
         progress?.Report((double)(i +1) / 100);
     }
}


// somewhere else in your code
public void StartProgress(){
    var progress = new Progress(p => Console.WriteLine($"Progress {p}"));
    DoStuff(progress);  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...