【发布时间】:2016-12-10 04:12:16
【问题描述】:
能否请您指出一个错误,为什么我让以下代码同步运行并在对 DB 的异步请求期间阻塞 UI?提前致谢。
我的视图模型:
public virtual bool MerchantsLoading { get; set; }
public virtual ObservableCollectionCore<Merchant> Merchants { get; set; }
public MerchantViewModel { //constructor
MerchantsLoading = true;
Merchants = SQLite.GetMerchants().Result;
SQLite.GetMerchants().ContinueWith(task => MerchantsLoading = false);
}
我的观点:
...
<dxg:GridControl ShowLoadingPanel="{Binding MerchantsLoading}" ItemsSource="{Binding Merchants}".../>
...
SQLite.GetMerchants():
public static async Task<ObservableCollectionCore<Merchant>> GetMerchants()
{
SQLiteConnection SqlConnection = new SQLiteConnection(MerchantDB);
var Merchants = new ObservableCollectionCore<Merchant.Merchant>();
try
{
await SqlConnection.OpenAsync();
SQLiteCommand myCommand = new SQLiteCommand("select * from merchant", SqlConnection);
DbDataReader myReader = await myCommand.ExecuteReaderAsync();
while (myReader.Read())
{
Merchants.Add(new Merchant.Merchant
{
ID = Convert.ToInt32(myReader["ID"]),
Name = Convert.ToString(myReader["Name"])
});
}
}
catch (Exception ex)
{
Messenger.Default.Send(new LogMessage { Message = "Ошибка в процедуре GetMerchants" });
Messenger.Default.Send(new LogMessage { Message = ex.ToString() });
}
finally
{
SqlConnection.Close();
}
return Merchants;
}
我添加了在 UserControl.Loaded 事件上触发的新函数,但 UI 仍然被阻止(viewmodel 构造函数现在为空):
public async void Loaded()
{
MerchantsLoading = true;
Merchants = await SQLite.GetMerchants();
await SQLite.GetMerchants().ContinueWith(task => MerchantsLoading = false);
}
DevExpress MVVM 框架的 EventToCommand 触发的 Loaded 事件:
<UserControl xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:ViewModels="clr-namespace:ORBKWorker.Merchant"
xmlns:Helpers="clr-namespace:ORBKWorker.Helpers"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol"
x:Class="ORBKWorker.Merchant.MerchantView"
mc:Ignorable="d"
DataContext="{dxmvvm:ViewModelSource Type={x:Type ViewModels:MerchantViewModel}}"
d:DesignHeight="800" d:DesignWidth="1920">
<UserControl.Resources>
<Helpers:IntToEmailType x:Key="IntToEmailType"/>
</UserControl.Resources>
<dxmvvm:Interaction.Behaviors>
<dxmvvm:EventToCommand EventName="Loaded" Command="{Binding LoadedCommand}"/>
</dxmvvm:Interaction.Behaviors>
<Grid>...
最后决定用BackgroundWorker来做:
public void GetMerchants()
{
MerchantsLoading = true;
BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += (sender, args) => Merchants = SQLite.GetMerchants();
bgw.RunWorkerCompleted += (sender, args) => MerchantsLoading = false;
bgw.RunWorkerAsync();
}
【问题讨论】:
-
据我所知,您的等待函数应该返回任务,即等待应该与返回任务的函数一起使用。 blog.stephencleary.com/2012/02/async-and-await.html
标签: c# .net wpf sqlite async-await