这两个简化代码之间有什么区别,特别是foreach部分。
public async Task UploadFilesAsync(IEnumerable<UploadFile> uploads)
{
uploads.ToList().ForEach(async upload =>
{
await UploadFileAsync(upload);
});
}
public async Task UploadFilesAsync(IEnumerable<UploadFile> uploads)
{
foreach (upload in uploads)
{
await UploadFileAsync(upload);
}
}
我知道第一个基本上创建了一个异步void操作,由于各种原因这不是最好的解决方案,但是第二个会做同样的事情,还是更多的公认实践呢?
答案 0 :(得分:0)
由于第一个方法包含一个不属于异步执行的foreach,它将启动内部匿名方法并退出。在UploadFileAsync方法完成后,匿名方法将完成。
第二个版本按顺序运行,因为foreach等待每次迭代(在调用MoveNext()之前),因此UploadFileAsync方法将在所有内部调用完成后退出。
您可以使用以下代码对其进行测试:
Y is :['Fractures' 'Second degree heat (thermal) burns'
'Traumatic injuries and disorders, unspecified' ..., 'Fractures'
'Poisoning, including poisoning-related asphyxia' 'Fractures']
所以,这不是对错的问题。它只是关于你想要实现的目标。如果您在UploadFilesAsync方法中创建了资源并希望在内部匿名方法中使用它们,那么使用第一个版本很容易遇到闭包问题。由于该方法在上载完成之前退出,因此在内部方法可以使用它们之前,将释放您创建的资源。
答案 1 :(得分:-1)
首先要做的事情。您的重点似乎是代码的异步/等待部分,所以我将首先回答。
我不相信从这个角度来看有任何不同
但除此之外还有一些有趣的差异
uploads.ToList()
,您正在迭代完整的IEnumerable<UploadFile> uploads
,而在方法#2中,您正在使用延迟执行的力量List<T>.ForEach
,您需要创建一个lambda expression
,其List<T>
将为await
中的每个元素调用其主体。如果它被调用很多次并且相当轻量级的工作,这可能相当昂贵。您可以在方法#2 现在,了解当您的代码遇到Task
调用时,几乎会暂停UploadFileAsync(upload)
完成代码。除非您想在该调用之后处理await'ing
的结果,否则您可以在没有public async Task UploadFilesAsync(IEnumerable<UploadFile> uploads)
{
foreach (upload in uploads)
{
UploadFileAsync(upload);
}
}
的情况下继续执行并继续执行,直到需要这些结果为止
Core Data
这样,您可以让来电者决定何时等待结果。