我有一个lambda表达式,里面有一个异步调用
=
我要在更改进度时调用 async 方法。
我收到以下警告:
此异步方法缺少“等待”运算符,将同步运行。 考虑使用“ await”运算符来等待非阻塞API调用
如何使该方法异步?
我应该用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);
}
类重写lambda吗?
答案 0 :(得分:3)
使用事件处理程序并在progress操作中引发它。事件处理程序将允许异步调用。
幸运的是,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;
}
现在,当报告进度时,事件处理程序可以进行异步调用。
引用Async/Await - Best Practices in Asynchronous Programming
另一种选择是创建自己的IProgress<T>
实现,该实现采用一个Func<Task<T>>
来允许异步调用,但这可能会显得过大。
答案 1 :(得分:2)
我认为您误解了Progress<T>
类的用法。编译器抱怨您的方法UploadFile
缺少await
运算符。您的lambda 将被调用时将异步执行。
下面是一个简短的摘要,介绍如何使用IProgressyT>
界面:
如果您的方法应支持进度报告,则可以将IProgress<T>
作为参数,并通过此对象传达其侵害性。它不执行受监视的操作。每次在Report()
上调用Progress<T>
方法时,都会执行您提供的Lambda。此Lambda通常用于更新UI。
这是一个例子。
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);
}