在控制器操作中进行异步调用

本文关键字:异步 调用 控制器 操作 | 更新日期: 2023-09-27 18:33:31

我有一个控制器操作,它获取文档类型的列表,然后对每种文档类型进行 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;
}

例外:

其他信息:异步操作不能在 这一次。异步操作只能在 异步处理程序或模块,或在页面中的某些事件期间 生命周期。如果在执行主页时发生此异常,请确保 页面标记为 <%@ 页面异步="true" %>。此例外可能 还指示尝试调用"异步 void"方法,即 在 ASP.NET 请求处理中通常不受支持。相反, 异步方法应返回一个任务,调用方应等待 它。

在控制器操作中进行异步调用

您的代码不正确。通过将异步 lambda 发送到 ForEach 扩展方法,您可以强制它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);;
}