If I fire off multiple async web requests, is it safe to append the result to a global variable, such as a StringBuilder? I know the order is not guaranteed.
-
Does this cause a lot of Task blocking?
-
Is this safe?
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();
}
No. You will wait on all of the tasks to complete, but this is by design. Otherwise, this is a fairly efficient way to write this.
This is not safe. As documented in StringBuilder: “Any instance members are not guaranteed to be thread safe.” (In this case,
Appendis an instance method.)Since you’re running this in a console application, the Append calls will happen on separate threads. You need some form of synchronization, such as using a
lockstatement around theAppendcall.Note that, if you were to use this same code in a Windows Forms or WPF application, however, the code which runs after
awaitwould be scheduled using the initialSynchronizationContext, which would cause it to always run on the UI thread, so you wouldn’t have thread synchronization issues. Since it’s in a console application, however, the continuations will run on separate threads.