这是针对用iOS
编写的Xamarin
应用。我的所有应用程序代码都在主线程中运行(即UI thread
)。
UI代码执行如下操作:
public async void ButtonClicked()
{
StartSpinner();
var data = await UpdateData();
StopSpinner();
UpdateScreen(data);
}
UpdateData
函数执行如下操作:
public Task<Data> UpdateData()
{
var data = await FetchFromServer();
TriggerCacheUpdate();
return data;
}
TriggerCacheUpdate
最终调用下面定义的以下函数
public Task RefreshCache()
{
var data = await FetchMoreDataFromServer();
UpdateInternalDataStructures();
}
我的问题是如何编写TriggerCacheUpdate
?要求是:
UpdateData
因此
ButtonClicked
等待RefreshCache
之前完成
仍在进行中。UpdateInternalDataStructures
需要在主(UI)线程上执行,即上面显示的所有其他代码都执行的线程。以下是我提出的一些备选方案:
public void TriggerCacheUpdate()
{
RefreshCache();
}
以上工作但会生成编译器警告。此外,RefreshCache
的异常处理无效。
public void TriggerCacheUpdate()
{
Task.Run(async() =>
{
await RefreshCache();
});
}
上述内容违反了要求2,因为UpdateInternalDataStructures
未在与其他所有内容相同的线程上执行。
我认为可行的替代方案是:
private event EventHandler Done;
public void TriggerCacheUpdate()
{
this.task = RefreshCache();
Done += async(sender, e) => await this.task;
}
Task RefreshCache() {
var data = await FetchMoreDataFromServer();
UpdateInternalDataStructures();
if (Done != null) {
Done(this, EventArgs.Empty);
}
}
以上是否有效?到目前为止,我还没有遇到过有限的测试问题。是否有更好的方法来撰写TriggerCacheUpdate
?
答案 0 :(得分:0)
很难说没有能够测试它,但看起来你的触发缓存更新方法很好,这是你的RefreshCache需要改变。在RefreshCache中,您没有在UI线程中等待“data”的结果返回,因此将ConfigureAwait设置为false。
public async Task RefreshCache()
{
var data = await FetchMoreDataFromServer().ConfigureAwait(false);
UpdateInternalDataStructures();
}
答案 1 :(得分:0)
您的事件处理程序是异步的。这意味着,即使您等待任务完成,您的UI仍然保持响应。因此,即使您要等待TriggerCacheUpdate返回,您的UI仍将保持响应。
但是,如果您确定自己对TriggerCachUpdate的结果不感兴趣,那么您可以在不等待的情况下启动任务:
public Task<Data> UpdateData()
{
var data = await FetchFromServer();
Task.Run( () => TriggerCacheUpdate());
return data;
}
注意:注意:您不知道TriggerCachUpdate何时完成,即使它成功结束或引发异常也不知道。另外:检查如果在前一个任务尚未完成的情况下启动新的TriggerCacheUpdate任务会发生什么。
对于想要使用Task.Factory.StartNew的用户,请参阅MSDN中有关它的讨论: