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();
}
Does this cause a lot of Task blocking?
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.
Is this safe?
This is not safe. As documented in StringBuilder: "Any instance members are not guaranteed to be thread safe." (In this case, Append is 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 lock statement around the Append call.
Note that, if you were to use this same code in a Windows Forms or WPF application, however, the code which runs after await would be scheduled using the initial SynchronizationContext, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With