2014-12-08 2 views
1

나는 컨트롤러 유형을 가져온 다음 각 문서 유형에 대해 웹 서비스 호출을하는 컨트롤러 동작을 사용합니다. 나는이 모든 것들을 한꺼번에 만들고 싶다. 그래서 그것들을 반복하는 것은 가장 길다. 내 코드가 맞는지는 모르겠다. 다른 코드를 사용해야하거나 내 코드가 올바르지 않은 경우.컨트롤러 내에서 비동기 호출 만들기 액션

작업 :

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; 
} 

예외 :

추가 정보 : 비동기 작업이 이 시간에 시작할 수 없습니다. 비동기 작업은 비동기 처리기 또는 모듈 내에서 또는 특정 라이프 사이클 동안에만 시작될 수 있습니다. 페이지를 실행하는 동안이 예외가 발생하면 페이지가 < % @ Page Async = "true"%>로 표시된 을 확인하십시오. 이 예외는 도 ASP.NET 요청 처리 내에서 일반적으로 지원되지 않는 인 "async void"메서드를 호출하려고했음을 나타낼 수 있습니다. 대신 비동기 메서드는 Task를 반환해야하고 호출자는 을 기다려야합니다.

답변

6

코드가 잘못되었습니다. 비동기 람다를 ForEach 확장 메소드에 보내면 UI 이벤트 핸들러 외부에서는 결코 좋은 아이디어가 아닌 async void이됩니다.

실제로 비동기로 통화는 모든 방법 비동기해야 :

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);; 
} 
+0

좋아, 내가 대해 읽고 있던 비동기 무효가있다. 그것은 내가 스택까지 비동기가 될 필요가 없어 보인다. 이제 인터페이스 서명을 변경해야합니까? Parallel.ForEach는 내가 원하는 것 (다른 것?)입니까? – MStodd

+0

I3arnon, 명확성을 위해 FindUpdate가 Async를 지원한다고 가정하고 documentUtility.FindDocuments (sc)에서 documentUtility.FindDocumentsAsync (sc)로 코드를 변경해야합니다. –

+0

@Son_of_Sam 그건 내 코드가 아니야, 그건 OP 다. 그러나 그것은 다른 방법들과 마찬가지로 사실입니다. – i3arnon

관련 문제