Reputation: 3161
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();
}
Upvotes: 3
Views: 4300
Reputation: 564771
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.
Upvotes: 5