2015-01-21 1 views
0

C#의 Threading.Tasks와 병렬로 HttpWebRequest 호출을 만드는 데 문제가 있습니까? (우분투에서 모노 컴파일을 사용하고 있습니까?) Google에 동기화 할 때 GET 요청을 25 회하면 총 소요 시간은 약 2 ~ 3 초입니다. 비동기 호출을하면 13 초 이상 걸립니다. 내 코드 :C#의 Threading.Tasks와 병렬로 HttpWebRequest 호출 만들기

using System; 
using System.Net; 
using System.Diagnostics; 
using System.Threading.Tasks; 

public class Google 
{ 
    public static void Main(string[] args) 
    { 

     Stopwatch timer1 = new Stopwatch(); 
     timer1.Start(); 

     for(int i=1; i<=25; i++){ 
      googleit(); 
     } 
     timer1.Stop(); 
     TimeSpan timeTaken1 = timer1.Elapsed; 


     Stopwatch timer2 = new Stopwatch(); 
     timer2.Start(); 

     int TaskCount = 25; 
     var tasks = new Task[TaskCount]; 
     for (var index = 0; index < TaskCount; index++) 
     { 
      tasks[index] = Task.Factory.StartNew(googleit); 
     } 
     Task.WaitAll(tasks); 

     timer2.Stop(); 
     TimeSpan timeTaken2 = timer2.Elapsed; 


     Console.WriteLine("Sync time: "); 
     Console.WriteLine(timeTaken1); 
     Console.WriteLine("async time: "); 
     Console.WriteLine(timeTaken2); 
    } 
    private static void googleit(){ 
     Stopwatch timer = new Stopwatch(); 
     timer.Start(); 

     HttpWebRequest request = WebRequest.Create("http://www.google.com") as HttpWebRequest; 
     request.Credentials = CredentialCache.DefaultCredentials; 

     HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
     response.Close(); 

     timer.Stop(); 
     TimeSpan timeTaken = timer.Elapsed; 
     Console.WriteLine(timeTaken); 
    } 
} 
+1

무엇보다 먼저 'ServicePointManager.DefaultConnectionsLimit = 500;'을 시도하십시오. – SimpleVar

+0

그리고 가장 확실하게 거기에있는'Console.WriteLine'을 사용하여 성능을 테스트하지 마십시오. 'googleit()'은 4 줄이어야합니다. – SimpleVar

+2

"async"코드는 실제로 비동기 요청을하지 않습니다. 동기식 요청을하는 작업을 가속화하고 있습니다. 'Task.Factory.StartNew()'대신'request.GetRequestAsync()'를 사용하도록 변경하십시오. –

답변

0

이 당신이 필요로하는 무엇을 얻어야한다 :

public static void SendAsync() 
{ 
    int TaskCount = 8; 
    var tasks = Enumerable.Range(0, TaskCount).Select(p => googleit()); 
    Task.WhenAll(tasks).Wait(); 
} 
private static async Task googleit() 
{ 
    HttpWebRequest request = WebRequest.Create("http://www.google.com") as HttpWebRequest; 
    request.Credentials = CredentialCache.DefaultCredentials; 

    var response = await request.GetResponseAsync(); 
    response.Close(); 
} 

그것은 비동기 적으로 모든 요청을 보낼 것이며, (블록)를 기다립니다.

코드에서 각 요청에 대한 작업을 작성하는 것이 었습니다. 예를 들어 코어가 2 개인 경우 TPL은 두 스레드간에 모든 작업을 분할하기로 결정할 때 두 스레드가 동기식으로 요청을 보냅니다. 하나의 핵심에서, 당신은 완전히 동기 실행을 원할 것입니다. 위의 코드에서 하나의 스레드가 모두 비동기 적으로 전송됩니다. 즉, 이전 요청을 기다리지 않고 요청을 게시하고 다음 요청을 전송합니다. 모든 요청이 전송 된 후 계속되는 - 귀하의 경우 'response.Close()'가 완료 될 때까지 스레드를 차단합니다.