【发布时间】:2020-07-21 06:44:54
【问题描述】:
我的要求是异步处理每个请求的图像,一旦处理完所有请求的图像,它们就会被压缩。所以为此我需要等到所有图像都处理完毕。
对列表中的每个项目使用for 循环来异步调用第二个API 的方法。但是,我需要等待对第二个 API 方法的所有调用执行,然后再转到代码中的下一行。
第一个 API:
public async void SegregateRecordsByRequestAndMerge(List<ClassB> listCDF, List<ClassA> records, string filePath)
{
List<ClassA> RequestList = records.GroupBy(x => x.RequestId)
.Select(g => g.First())
.ToList();
Task[] taskList = new Task[RequestList.Count];
for (int i = 0; i < RequestList.Count; i++) // reqList in RequestList)
{
ClassA reqList = new ClassA();
reqList = RequestList[i];
List < ClassA> recordsByRequest = records.Where(x => x.RequestId == reqList.RequestId).ToList();
ModelA serviceInput = new ModelA();
serviceInput.ClassBProperty = listCDF;
serviceInput.ClassAProperty = recordsByRequest;
taskList[i] = (Task.Factory.StartNew(() => ProcessImages(serviceInput, "myroute/processimage")));
}
Task.WaitAll(taskList, 600000);
}
这就是服务调用的方式
public void ProcessImages(CodingRecordAndCDFModel myServiceInput, string resource)
{
var client = new ServiceClient(BaseUrl)
{
Resource = resource
};
client.Post(JsonConvert.SerializeObject(myServiceInput).ToString());
}
第二个 API(图像处理器):
[HttpPost, Route("myroute/processimage"), ResponseType(typeof(string))]
public void GeneratePDFs([FromBody] string pdfServiceInput) {
if (!ModelState.IsValid) {
throw new Exception();
}
ModelA myServiceModel = new ModelA();
myServiceModel = JsonConvert.DeserializeObject <ModelA> (pdfServiceInput);
//// Logic to Process images
}
我面临的问题是,即使我使用的是 WaitAll(),也会引发任务取消异常。 在第 2 个 API 中的方法完全执行之前,控件返回到第 1 个 API。
我尝试了多种方法,例如使用Parallel.ForEach()、Task.Whenall()、Task.Delay、TaskCreationOptions.LongRunning,但它们都不起作用……它们都抛出了任务被取消的异常。
我需要控件等到所有对第二个 API 的调用都返回到第一个 API,然后执行一些其他逻辑。
有人可以建议应该做什么吗?或者有什么更好的方法来处理这个要求?
编辑 1:
我认为问题在于我正在尝试异步调用一个方法,这将创建 2 个不同的异步方法调用...并且由于我在每个异步方法上使用 await 或 waitall,所以第一次调用的执行是完成后,即使第二个 API 中有另一个线程在运行,控件也会返回到第一个 API。
如果有办法等待 for 循环或等待所有单独的异步调用返回,那么这将是解决方案。
【问题讨论】:
-
只是提醒一下,idk 它完全相关,async/await 在 asp.net 核心与说具有主线程的 ui 应用程序中的行为不同:blog.stephencleary.com/2017/03/…
-
也许问题出在第二个 API 上。你在那里使用异步方法吗?任何异步\等待?如果是这样,您需要将 async 关键字添加到 API 并设置返回类型 Task 而不是 void(即使您没有返回任何内容)
-
是的,我也尝试过,使第二个 API 方法异步并返回任务。但它也不起作用。我想我理解了这个问题,但不知道如何解决它。请阅读编辑 1 了解可能发生的情况。
-
您正在使用的这个 ServiceClient 类的命名空间是什么?也许您可以提供一个文档链接?
-
我的意思是 - 我发现表示 REST 请求的方法是同步的,这很奇怪。如果这个
ServiceClient类有PostAsync方法,我不会感到惊讶。在这种情况下,它会返回一个Task或更可能是Task<TResponse>,然后您可以根据需要进行处理,例如,将其添加到您的taskList。当然,在这种情况下,您还可以将ProcessImages方法的签名更改为Task ProcessImage(...)并实际返回任务:return client.PostAsync(...);
标签: .net .net-core asp.net-core-webapi .net-core-3.1