具有异步lambda表达式的异步方法

时间:2018-09-21 12:47:15

标签: c# asp.net-core

我有一个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吗?

2 个答案:

答案 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);  
}