异步方法中的StringBuilder

use*_*753 3 c# visual-studio-2010 async-await .net-4.5

如果我触发了多个异步Web请求,将结果附加到全局变量(例如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();
}
Run Code Online (Sandbox Code Playgroud)

Ree*_*sey 5

这会导致很多任务阻塞吗?

不会。您将等待所有任务完成,但这是设计使然。否则,这是一种相当有效的编写方式。

这样安全吗?

这不安全。如StringBuilder中所述:“不保证任何实例成员都是线程安全的。” (在这种情况下,Append是一个实例方法。)

由于您是在控制台应用程序中运行的,因此Append调用将在单独的线程上进行。您需要某种形式的同步,例如lockAppend调用周围使用一条语句。

请注意,但是,如果要在Windows Forms或WPF应用程序中使用相同的代码,await则将使用initial来计划在此之后运行的代码SynchronizationContext,这将使其始终在UI线程上运行,因此您不会有线程同步问题。由于它在控制台应用程序中,因此继续将在单独的线程上运行。