在C#类初始化器中调用多个异步操作是否会引发并发问题?
问题分析
给定C#类:
public class MyData { public int Value1 { get; set; } public int Value2 { get; set; } }
采用如下方式实例化并初始化:
var myInstance = new MyData { Value1 = await MyFirstAsync(), Value2 = await MySecondAsync() };
假设MySecondAsync()与MyFirstAsync()依赖同一非线程安全资源,请问这种写法是否会引发并发问题,或存在其他需规避的潜在问题?
回答
这种写法不会引发并发问题,核心原因是对象初始化器里的赋值操作是串行执行的:
- 先执行
Value1 = await MyFirstAsync():调用MyFirstAsync()并等待它完全执行完毕,这段时间里MySecondAsync()不会被启动 - 只有当
MyFirstAsync()执行完成、给Value1完成赋值后,才会执行Value2 = await MySecondAsync(),等待MySecondAsync()完成并赋值
因为两个异步方法是先后执行,不会同时运行,所以它们不会同时访问那个非线程安全资源,自然不会触发并发冲突。
潜在需要注意的点
- 异常场景的临时对象处理:如果初始化过程中
MySecondAsync()抛出异常,此时MyData对象已经被创建且Value1已赋值,但这个对象不会被赋值给myInstance,最终会被GC回收,不会出现“部分初始化的实例被误用”的情况,无需额外担心。 - 性能优化的风险:如果想通过并发执行两个异步方法提升性能,直接改用
Task.WhenAll的写法会触发并发访问非线程安全资源的问题,比如:
这种写法会让两个方法同时运行,此时必须给非线程安全资源添加同步锁(比如var task1 = MyFirstAsync(); var task2 = MySecondAsync(); await Task.WhenAll(task1, task2); var myInstance = new MyData { Value1 = task1.Result, Value2 = task2.Result };lock)来避免并发冲突。
内容的提问来源于stack exchange,提问作者R26
相关产品推荐
相关产品推荐

