【发布时间】:2015-11-30 05:56:26
【问题描述】:
编辑:因此,似乎让方法返回 void 而不是任务意味着异常在错误(意外?)上下文中传播。 但是,我的 IDE (Xamarin) 仍然在我调用 AttemptDatabseLoad() 的构造函数中大惊小怪
"该语句不等待并执行当前方法 在呼叫完成之前继续。考虑使用“等待” 运算符或调用 'Wait' 方法"
为什么要大惊小怪?当然,使用异步方法的全部目的正是为了让程序继续在主线程上执行。
我已经阅读了一些关于 async 和 await 的内容,因为我需要为我正在制作的应用程序加载一些异步数据。我在很多地方读到过让异步方法返回 void 是不好的做法(触发事件的情况除外),并且我理解保持对任务的句柄的原因。 但是,我看不出我在下面写的内容有任何逻辑错误,所以我的问题是双重的:为什么我当前的代码实践不佳?应该怎么改写?
private const int MAX_CONNECTION_ATTEMPTS = 10;
private int ConnectionAttempts = 0;
//Constructor
public DataLoader()
{
//First load up current data from local sqlite db
LoadFromLocal();
//Then go for an async load from
AttemptDatabaseLoad();
}
public async void AttemptDatabaseLoad()
{
while(ConnectionAttempts < MAX_CONNECTION_ATTEMPTS){
Task<bool> Attempt = TryLoad ();
bool success = await Attempt;
if (success) {
//call func to load data into program memory proper
}else{
ConnectionAttempts++;
}
}
}
//placeholder for now
public async Task<bool> TryLoad()
{
await Task.Delay(5000);
return false;
}
【问题讨论】:
-
在构造函数中的异步调用没有多大意义——新对象不仅半未初始化,你甚至不知道什么时候它是安全的使用。
-
我很困惑。当然,每当调用 await 时,执行就会分裂到一个新的上下文中并在主上下文中继续?所以 AttemptDatabaseLoad() 不应该阻塞主(或调用)线程,因为对象构造将和往常一样快。
-
不,它不会阻塞,那是问题。您将返回一个可能包含或不包含有效数据但您无法知道的对象。您甚至不知道要等多久才能安全使用该对象。 Yuval 的回答和 krim 的回答中的链接解释为避免这种情况
标签: c# asynchronous async-await