2012-07-10 22 views
1

목록에있는 많은 URL을 호출하기 위해 BeginGetResponse 메서드를 사용하고 싶습니다. 우리가 사용하는 http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse(v=vs.95).aspx 웹 응용 프로그램의 BeginGetResponse

  1. 예에 따라 : 나는 이것을 구현하는 방법에 대한이 개 질문이

    public static ManualResetEvent allDone= new ManualResetEvent(false); 
    

    현명한 웹 응용 프로그램에서 정적 멤버를 사용하는 것입니다 다른 스레드와 공유 되었기 때문에? 이것이 문제의 원인이 될 수 있습니까?

    1. 모든 콜백이 완료된 것을 어떻게 알 수 있습니까? 최적의 워크 플로우가 이벤트를 필요로하지 않습니다

      int total = urls.Count; 
      ManualResetEvent evt = new ManualResetEvent(); 
      ConcurrentBag<WebResponses> responses = new ConcurrentBag<WebResponse>(); 
      
      foreach(Uri in uri) 
      { 
          HttpWebRequest req = ...; 
          req.BeginGetResponse(res=> 
          { 
           WebResponse res = req.EndGetResponse(); 
      
           // do what you need with the response. 
           // maybe add it to a collection so you can report on it later: 
           responses.Add(res); 
      
           if(Interlocked.Decrement(ref total) == 0) 
           { 
            // this was the last response. set event. 
            evt.Set(); 
           } 
          }, null); 
      } 
      
      evt.Wait(); 
      
      foreach(WebResponse res in responses) 
      { 
          // report something about the response. 
      } 
      

      참고 : 난 당신이 그런 짓을하려는 생각

    감사 결과에

답변

1
  1. 완료를 위해 주 스레드에서 기다리고 싶다면이 솔루션은 그리 좋지 않습니다. 첫 번째 요청은 이벤트의 상태를 '설정'으로 변경합니다. 따라서 주 스레드는 첫 번째 요청이 완료된 후에도 계속 실행됩니다.
  2. A는 당신이 CountdownEvent를 사용하는 것이 좋습니다 :

    using(var countdownEvent = new CountdownEvent(list.Count)) 
        { 
         // launch requests with countdownEvent.Signal(); in the end 
         countdownEvent.Wait(); 
        } 
    

    당신은 RequestState 내부 countdownEvent에 대한 참조를 저장해야합니다.또한 시간 제한을 제어하는 ​​것을 잊지 마십시오. ThreadPool.RegisterWaitForSingleObject으로 새 스레드를 시작하십시오.

1

를 요약 보고서를 할 필요가 . 여분의 크레디트를 얻으려면 이벤트를 설정하는 if 내부에 최종 로직을 이동하십시오.

또한이 코드는 테스트되지 않았으므로 오류 처리 기능이 없으므로이 코드는 오류 처리 기능이 없으므로이 코드를 추가해야합니다.

3

당신이 이벤트를 사용할 수 있지만, 나는 Task<T>과의 FromAsync method를 사용하는 것이 좋습니다하려는 TaskFactory class과 같이 :

// Execution of tasks starts here because of the 
// call to ToArray. 
Task<WebResponse>[] tasks = uris.Select(u => { 
    // Create the request. 
    WebRequest req = ...; 

    // Make the call to return the response asynchronously with 
    // a Task. 
    return Task.Factory.FromAsync(req.BeginGetResponse, 
     req.EndGetResponse, null); 
}).ToArray(); 

당신은 쉽게를 사용하여 Task<T> 모든 인스턴스에 대기하는 일단 계속 너무 같은 TaskFactory 클래스 ContinueWhenAll method : 위의

Task.Factory.ContinueWhenAll(tasks, t => { 
    // Note that t is an array of Task, so you have to cast 
    // each element to a Task<WebRequest>. 
    // Process all of them here. 
}); 

참고 반환 당신이 기다려야 할 것 Task 또는 완료되었을 때 계속 진행됩니다 (통지가 우려되는 경우). 당신이 .NET 4.5을 사용하는 경우

, 당신은 TaskFactory 클래스에 ContinueWhenAll 방법을 사용할 필요는 없지만, 작업 수행 Task 클래스에 WhenAll method를 사용할 수 있습니다

// Note that work does not start here yet because of deferred execution. 
// If you want it to start here, you can call ToArray like above. 
IEnumerable<Task<WebResponse>> tasks = uris.Select(u => { 
    // Create the request. 
    WebRequest req = ...; 

    // Make the call to return the response asynchronously with 
    // a Task. 
    return Task.Factory.FromAsync(req.BeginGetResponse, 
     req.EndGetResponse, null); 
}); 

// Execution will start at this call: 
Task<Task<WebRequest>[]> allTasks = Task.WhenAll(tasks); 

// Continue or wait here. 

위 내용은 it was revealed that .NET 3.5 was being used 앞에 있었던 것입니다.

+0

안녕 캐스퍼 불행히도 나는 .NET 3.5를 사용하고있다. 그러나 기다리는 것이 있다는 것을 아는 것은 좋다. :) – Tsahi

+0

조금 설명 할 수 있겠습니까? 이 방법을 사용하여 요청의 응답을 얻는 방법은 무엇입니까? –