我有一个控制器操作,它获取文档类型列表,然后为每个文档类型进行Web服务调用。我想立刻制作这些,所以循环它们只需要最长的一个。我不知道我的代码是否正确,我还需要做其他事情,或者我的代码是不正确的。
动作:
public ActionResult GetPlan(MemberViewModel request)
{
DocService ds = new DocService();
List<DocType> docTypes = ds.GetDocTypesForPlan(request.PlanId);
List<CoverageDocument> coverageDocuments = ds.GetDocumentsForDocTypes(docTypes);
return View(coverageDocuments);
}
GetDocumentsForDocTypes:
public List<CoverageDocument> GetDocumentsForDocTypes(List<DocType> planDocTypes)
{
List<CoverageDocument> planDocuments = new List<CoverageDocument>();
DocumentUtility documentUtility = new DocumentUtility();
int lastYear = DateTime.Now.Year - 1;
planDocTypes.ForEach(async (docType) =>
{
DocumentUtility.SearchCriteria sc = new DocumentUtility.SearchCriteria();
sc.documentType = docType;
Dictionary<long, Tuple<string, string>> documentList = await documentUtility.FindDocuments(sc);
documentList.ToList().ForEach((document) =>
{
CoverageDocument doc = this.coverageDocumentConstructor(document);
planDocuments.Add(doc);
});
});
return planDocuments;
}
例外:
附加信息:无法启动异步操作 这次。异步操作只能在一个内部启动 异步处理程序或模块或在页面中的某些事件期间 生命周期。如果在执行页面时发生此异常,请确保 页面标记为&lt;%@ Page Async =“true”%&gt;。这个例外可能 还表示尝试调用“异步void”方法,即 通常在ASP.NET请求处理中不受支持。相反, 异步方法应该返回一个Task,并且调用者应该等待 它
答案 0 :(得分:6)
您的代码不正确。通过向ForEach扩展方法发送异步lambda,您强制它为async void
,这在UI事件处理程序之外永远不是一个好主意。
要实际上是异步的,您的呼叫需要始终保持异步:
public async Task<ActionResult> GetPlan(MemberViewModel request)
{
DocService ds = new DocService();
List<DocType> docTypes = ds.GetDocTypesForPlan(request.PlanId);
List<CoverageDocument> coverageDocuments = await ds.GetDocumentsForDocTypesAsync(docTypes);
return View(coverageDocuments);
}
public async Task<List<CoverageDocument>> GetDocumentsForDocTypesAsync(List<DocType> planDocTypes)
{
DocumentUtility documentUtility = new DocumentUtility();
int lastYear = DateTime.Now.Year - 1;
var planDocuments = await Task.WhenAll(planDocTypes.Select(async (docType) =>
{
DocumentUtility.SearchCriteria sc = new DocumentUtility.SearchCriteria();
sc.documentType = docType;
return await documentUtility.FindDocuments(sc).Select((document) => this.coverageDocumentConstructor(document))
}));
return planDocuments.SelectMany(doc => doc);;
}