[英]Async method with an async lambda expression
我有一个lambda表达式,里面有一个异步调用
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>
类重写lambda吗?
使用事件处理程序并在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;
}
因此,现在,当报告进度时,事件处理程序可以进行异步调用。
另一个选择是创建您自己的IProgress<T>
实现,该实现采用Func<Task<T>>
,该函数可以进行异步调用,但可能会过大。
我认为您误解了Progress<T>
类的用法。 编译器抱怨说,您的方法UploadFile
没有await
操作符。 你拉姆达将执行异步的,什么时候会被调用。
下面是一个简短的摘要,介绍如何使用IProgressyT>
接口:
如果您有一个应支持进度报告的方法,则可以将IProgress<T>
作为参数并通过此对象传达其发生率。 它不执行监视的操作。 每次在Progress<T>
上调用Report()
方法时,都会执行您提供的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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.