2012-10-19 67 views
3

如果我關閉多個異步Web請求,是否可以將結果附加到全局變量(例如StringBuilder)?我知道訂單不能保證。異步方法中的StringBuilder

  1. 這是否會導致很多任務阻塞?

  2. 這是安全嗎?

private static StringBuilder sb = new StringBuilder(); 

private static async Task AccessTheWebAsync() 
{ 
    HttpClient client = new HttpClient(); 
    HttpResponseMessage response = await client.GetAsync(@"http://www.google.com/"); 
    sb.Append(response.StatusCode).Append(Environment.NewLine);   
} 

static void Main(string[] args) 
{ 
    List<Task> tasks = new List<Task>(); 
    for (int i = 0; i < 10; i++) 
     tasks.Add(AccessTheWebAsync()); 
    Task.WaitAll(tasks.ToArray()); 
    Console.Write(sb.ToString()); 
    Console.ReadLine(); 
} 

回答

4

這是否造成了大量的任務堵?

不可以。您會等待所有任務完成,但這是設計。否則,這是寫這個的一個相當有效的方法。

這是安全嗎?

這並不安全。如StringBuilder所述:「任何實例成員不保證是線程安全的。」 (在這種情況下,Append是一種實例方法。)

由於您在控制檯應用程序中運行此操作,因此Append調用將發生在單獨的線程上。您需要某種形式的同步,例如在Append調用周圍使用lock聲明。

請注意,如果您要在Windows窗體或WPF應用程序中使用相同的代碼,則會在await之後運行的代碼將使用初始SynchronizationContext進行調度,這會導致它始終在UI線程上運行,所以你不會有線程同步問題。但是,由於它在控制檯應用程序中,所以延續將在單獨的線程上運行。

+0

[您可以添加同步上下文到您的控制檯應用程序,如果你這麼傾向](http://blogs.msdn.com/b/pfxteam/archive/2012/02/02/await-synchronizationcontext-and-控制檯應用程序,部分3.aspx)。 – Servy

+1

這是我猜想的更多後續行動。那麼它會更合乎邏輯,可能會使簽名'私有靜態異步任務 AccessTheWebAsync()'返回'response.StatusCode',然後最後在'WaitAll'循環後面並附加所有'Result's? – user17753

+0

@ user17753是的,實際上,這可能會更好。 – Servy