C#不允许使用异步构造函数。构造函数的目的是进行一些简短的初始化后快速返回。您不希望等待实例即构造函数返回。因此,即使异步构造函数是可能的,构造函数也不是执行长时间操作或启动后台线程的地方。构造函数的唯一目的是将实例或类成员初始化为默认值或捕获的构造函数参数。您始终先创建实例,然后在该实例上调用
DoSomething()
。异步操作也不例外。您始终要延迟成本高昂的成员初始化。
有几种解决方案可以避免使用异步构造函数。
- 通过使用
Lazy<T>
或AsyncLazy<T>
(需要通过NuGet包管理器安装Microsoft.VisualStudio.Threading包),可以使用简单的替代方案。 Lazy<T>
允许延迟实例化或分配昂贵的资源。
public class OrderService
{
public List<object> Orders => this.OrdersInitializer.GetValue();
private AsyncLazy<List<object>> OrdersInitializer { get; }
public OrderService()
=> this.OrdersInitializer = new AsyncLazy<List<object>>(InitializeOrdersAsync, new JoinableTaskFactory(new JoinableTaskContext()));
private async Task<List<object>> InitializeOrdersAsync()
{
await Task.Delay(TimeSpan.FromSeconds(5));
return new List<object> { 1, 2, 3 };
}
}
public static void Main()
{
var orderService = new OrderService();
orderService.Orders.Add(4);
}
你可以使用方法而不是属性来公开数据。
public class OrderService
{
private List<object> Orders { get; set; }
public async Task<List<object>> GetOrdersAsync()
{
if (this.Orders == null)
{
await Task.Delay(TimeSpan.FromSeconds(5));
this.Orders = new List<object> { 1, 2, 3 };
}
return this.Orders;
}
}
public static async Task Main()
{
var orderService = new OrderService();
List<object> orders = await orderService.GetOrdersAsync();
}
使用一个必须在实例使用前调用的
InitializeAsync
方法。
public class OrderService
{
private List<object> orders;
public List<object> Orders
{
get
{
if (!this.IsInitialized)
{
throw new InvalidOperationException();
}
return this.orders;
}
private set
{
this.orders = value;
}
}
public bool IsInitialized { get; private set; }
public async Task<List<object>> InitializeAsync()
{
if (this.IsInitialized)
{
return;
}
await Task.Delay(TimeSpan.FromSeconds(5));
this.Orders = new List<object> { 1, 2, 3 };
this.IsInitialized = true;
}
}
public static async Task Main()
{
var orderService = new OrderService();
await orderService.InitializeAsync();
}
通过将昂贵的参数传递给构造函数实例化实例。
public class OrderService
{
public List<object> Orders { get; }
public async Task<List<object>> OrderService(List<object> orders)
=> this.Orders = orders;
}
public static async Task Main()
{
List<object> orders = await GetOrdersAsync();
var orderService = new OrderService(orders);
}
private static async Task<List<object>> GetOrdersAsync()
{
await Task.Delay(TimeSpan.FromSeconds(5));
return new List<object> { 1, 2, 3 };
}
使用工厂方法和私有构造函数。
public class OrderService
{
public List<object> Orders { get; set; }
private OrderServiceBase()
=> this.Orders = new List<object>();
public static async Task<OrderService> CreateInstanceAsync()
{
var instance = new OrderService();
await Task.Delay(TimeSpan.FromSeconds(5));
instance.Orders = new List<object> { 1, 2, 3 };
return instance;
}
}
public static async Task Main()
{
OrderService orderService = await OrderService.CreateInstanceAsync();
}
await
,您将在调用时看到警告。请勿忽略此类警告;它可能会导致死锁;您的用户界面可能会永久冻结。 - ToolmakerSteve