【发布时间】:2021-06-01 05:57:55
【问题描述】:
您好最近我在 .net core web api 项目中工作,该项目正在从外部 api 下载文件。 在这个 .net 核心 api 最近发现了一些问题,而文件数量超过 100 个。API 正在下载最多 50 个文件并跳过其他文件。 WebAPI 部署在 AWS Lambda 上,超时时间为 15 分钟。
由于下载过程较长,实际操作超时
public async Task<bool> DownloadAttachmentsAsync(List<DownloadAttachment> downloadAttachment)
{
try
{
bool DownloadFlag = false;
foreach (DownloadAttachment downloadAttachment in downloadAttachments)
{
DownloadFlag = await DownloadAttachment(downloadAttachment.id);
//update the download status in database
if(DownloadFlag)
{
bool UpdateFlag = await _DocumentService.UpdateDownloadStatus(downloadAttachment.id);
if (UpdateFlag)
{
await DeleteAttachment(downloadAttachment.id);
}
}
}
return true;
}
catch (Exception ext)
{
log.Error(ext, "Error in Saving attachment {attachemntId}",downloadAttachment.id);
return false;
}
}
文件服务代码
public async Task<bool> UpdateAttachmentDownloadStatus(string AttachmentID)
{
return await _documentRepository.UpdateAttachmentDownloadStatus(AttachmentID);
}
和数据库更新代码
public async Task<bool> UpdateAttachmentDownloadStatus(string AttachmentID)
{
using (var db = new SqlConnection(_connectionString.Value))
{
var Result = 0; bool SuccessFlag = false;
var parameters = new DynamicParameters();
parameters.Add("@pm_AttachmentID", AttachmentID);
parameters.Add("@pm_Result", Result, System.Data.DbType.Int32, System.Data.ParameterDirection.Output);
var result = await db.ExecuteAsync("[Loan].[UpdateDownloadStatus]", parameters, commandType: CommandType.StoredProcedure);
Result = parameters.Get<int>("@pm_Result");
if (Result > 0) { SuccessFlag = true; }
return SuccessFlag;
}
}
如何将此异步任务移动到并行运行?并得到结果?我尝试了以下代码
var task = Task.Run(() => DownloadAttachment( downloadAttachment.id));
bool result = task.Result;
这种方法好吗?怎样才能提高性能?如何从每个并行任务中获取结果并根据成功标志更新到 DB 和删除?还是这个错误是由于 AWS 超时造成的?
请帮忙
【问题讨论】:
-
什么是
_DocumentService?它是线程安全的吗? -
@SvyatoslavDanyliv : 那是更新数据库中文件下载标志的数据库操作部分
-
因此您不能并行执行此操作。您必须为每个任务创建新的 DbContext。
-
您可以进行 HTTP 调用并异步保存到数据库,这比您尝试的要容易得多。那是
async/await的工作,而不是Task.Run。启动一个异步操作只是为了阻止它的任务是没有意义的。然后阻塞任务本身 -
如果
DownloadAttachment已经是异步的,那么Task.Run(() => DownloadAttachment( downloadAttachment.id)).Result的意义何在?如果这甚至有效,它仍然会启动并阻止相同的操作。但现在,它只返回由DownloadAttachment返回的相同任务。如果你想启动多个DownloadAttachment调用,你可以使用例如var tasks=downloadAttachments.Select(att=>DownladAttachment(att.Id));。但这会立即启动所有这些,这可能不是您想要的
标签: c# .net-core aws-lambda task-parallel-library asp.net-core-webapi