如果我触发多个异步 Web 请求,将结果附加到全局变量(例如 StringBuilder
)是否安全?我知道不能保证顺序。
这会导致很多 Task 阻塞吗?
这样安全吗?
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?
没有。您将等待所有任务完成,但这是设计使然。否则,这是一种相当有效的编写方式。
Is this safe?
这不安全。如 StringBuilder 中所述:“不保证任何实例成员都是线程安全的。” (在这种情况下,Append
是一个实例方法。)
由于您是在控制台应用程序中运行它,因此追加调用将发生在单独的线程上。您需要某种形式的同步,例如在 Append
调用周围使用 lock
语句。
请注意,如果您要在 Windows 窗体或 WPF 应用程序中使用相同的代码,则在 await
之后运行的代码将使用初始 SynchronizationContext
,这会导致它始终在 UI 线程上运行,因此您不会遇到线程同步问题。但是,由于它在控制台应用程序中,延续将在单独的线程上运行。
关于c# - 异步方法中的 StringBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12980932/