2012-10-19 68 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