Hello StackOverflow社区,
我知道这篇文章中有很多代码,但是我想给大家,社区尽可能多的关于这里发生的事情的图片,以便有人可以帮助我弄清楚我的问题是。
最近,对于我正在从事的项目,我们决定从MvvmCross 5.7.0升级到6.2.2。我已经设法使我们的UWP应用程序成功完成了初始化和设置过程。我们为其注册应用程序启动的第一个viewmodel也开始初始化。但是,我发现我的虚拟机初始化挂在特定的代码行上(如下面的代码所示)。最奇怪的部分是应用初始化代码中调用的类似方法,无需挂起/死锁即可完美运行,因此我不确定有什么不同。这是我的viewmodel代码的简化版本,用于说明:
public class MyViewModel : BaseAuthenticatedTabBarViewModel, IMvxViewModel<int>
{
private int? _settingValue;
public override async Task Initialize()
{
//Some irrelevant initialization code
Exception e = null;
try
{
//This line of code never returns
_settingValue = _settingValue ?? await AppSettingService.GetSettingValue();
}
catch (Exception ex)
{
e = ex;
}
if (e != null)
{
await HandleCatastrophicError(e);
}
}
}
AppSettingService.GetSettingValue()方法如下:
public async Task<int?> GetCurrentEventId()
{
return await GetNullableIntSetting("SettingValue");
}
private static async Task<int?> GetNullableIntSetting(string key)
{
try
{
var setting = await SettingDataService.SettingByName(key);
if (setting != null)
{
return string.IsNullOrEmpty(setting.Value) ? (int?)null : Convert.ToInt32(setting.Value);
}
}
catch (Exception ex)
{
//Handle the exception
}
return null;
}
SettingDataService的所有代码:
public class SettingDataService : DataService<SettingDataModel>, ISettingDataService
{
public async Task<SettingDataModel> SettingByName(string name)
{
try
{
var values = (await WhereAsync(e => e.Name == name));
return values.FirstOrDefault();
}
catch(Exception ex)
{
//Handle the exception
}
return null;
}
}
最后,WhereAsync()的实现在名为DataService的类中,如下所示:
public virtual async Task<IEnumerable<T>> WhereAsync(System.Linq.Expressions.Expression<Func<T, bool>> condition, SQLiteAsyncConnection connection = null)
{
return await (connection ?? await GetConnectionAsync())
.Table<T>()
.Where(condition)
.ToListAsync();
}
非常感谢您的提前帮助
编辑:忘记也添加此关键代码以进一步帮助你们:
protected async Task<SQLiteAsyncConnection> GetConnectionAsync()
{
SQLiteAsyncConnection connection = null;
while (true)
{
try
{
connection = Factory.Create(App.DatabaseName);
// This line of code is the culprit. For some reason this hangs and I can't figure out why.
await connection.CreateTableAsync<T>();
break;
}
catch (SQLiteException ex)
{
if (ex.Result != Result.CannotOpen && ex.Result != Result.Busy && ex.Result != Result.Locked)
{
throw;
}
}
await Task.Delay(20);
}
return connection;
}
答案 0 :(得分:3)
我怀疑您正在呼叫堆栈中更远的某个地方呼叫Task.Wait
或Task<T>.Result
。或者,如果您不这样做,则MvvmCross is可能是doing it for you。从UI上下文调用时,它将cause a deadlock。
个人而言,我更喜欢ViewModels应该始终同步构造并且不能具有异步“初始化”的方法。也就是说,它们必须将自己(同步)构造为“正在加载”状态,并且这种构造可以启动异步操作,该异步操作随后会将它们更新为“已加载”状态。同步初始化模式意味着更改视图时永远不会有不必要的延迟。您的用户可能只会看到微调框或加载消息,但至少他们会看到某物。请参阅我在async MVVM data binding上的文章以获取有助于解决此问题的模式,并注意其中有一个newer version of the helper types in that article。