2017-09-23 44 views
0

我對於異步任務有點陌生。C#同時運行許多異步任務

我有一個功能,可以從特定的大學網站上獲取學生證和數據,並提供所需的ID。

private static HttpClient client = new HttpClient(); 
    public static async Task<Student> ParseAsync(string departmentLink, int id, CancellationToken ct) 
    { 
     string website = string.Format(departmentLink, id); 
     try 
     { 
      string data; 
      var stream = await client.GetAsync(website, ct); 
      using (var reader = new StreamReader(await stream.Content.ReadAsStreamAsync(), Encoding.GetEncoding("windows-1256"))) 
       data = reader.ReadToEnd(); 

      //Parse data here and return Student. 
     } catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 

它正常工作。雖然有時我需要爲很多學生運行這個功能,所以我用下面的

 for(int i = ids.first; i <= ids.last; i++) 
     { 
      tasks[i - ids.first] = ParseStudentData.ParseAsync(entity.Link, i, cts.Token).ContinueWith(t => 
      { 
       Dispatcher.Invoke(() => 
       { 
        listview_students.Items.Add(t.Result); 
        //Students.Add(t.Result); 
        //lbl_count.Content = $"{listview_students.Items.Count}/{testerino.Length}"; 
       }); 
      }); 
     } 

我存儲在數組任務後等待他們。

只要學生人數介於(0,〜600?)之間,這也可以很好地工作,這是隨機的。 然後對於仍然沒有被解析過的所有其他學生拋出任務被取消

請記住,我從不使用取消標記。

我需要在如此多的學生上運行這個函數,它可以完全達到〜9000個異步任務。那麼發生了什麼?

回答

2

當您在如此短的時間內排隊處理9000個請求時,您基本上會在網站上創建拒絕服務攻擊。這不僅會導致你的錯誤,但它可能會使網站失效。最好將併發請求的數量限制在一個更合理的值(比如說30)。雖然有可能是幾種方法可以做到這一點,我想到的是:

private async Task Test() 
{ 
    var tasks = new List<Task>(); 
    for (int i = ids.first; i <= ids.last; i++) 
    { 
    tasks.Add(/* Do stuff */); 
    await WaitList(tasks, 30); 
    } 
} 

private async Task WaitList(IList<Task> tasks, int maxSize) 
{ 
    while (tasks.Count > maxSize) 
    { 
    var completed = await Task.WhenAny(tasks).ConfigureAwait(false); 
    tasks.Remove(completed); 
    } 
} 

其他方法可能利用使用.NET類生產者/消費者模式,如BlockingCollection