繁体   English   中英

WPF从数据库冻结UI检索数据

[英]Wpf retrieving data from database freeze UI

每当我获得UI锁定时,我都会从数据库异步检索数据时遇到问题。

private async void RetrieveHotlist(object sender, RoutedEventArgs e) //button click
    {
        var hotItems = new ObservableCollection<HotItem>();
        await Task.Factory.StartNew(() =>
            {

                try
                {
                    var serv = "xxx";
                    string connStr = Common.GetConStrEF(serv + "\\" + Common.DBLOGIN_INSTANCE,
                                                        Common.DBLOGIN_DBNAME, Common.DBLOGIN_USER, Common.DBLOGIN_PASSWORD);
                    var dataModel = new xxxxDataModel(connStr);

                    foreach (var category in dataModel.SpecialNumberCategory)  //retrieving database CreateObjectSet<SpecialNumberCategory>("SpecialNumberCategory"); //ObjectContext
                    {
                        var item = new HotItem() {  Name = category.Name };
                        hotItems.Add(item);
                    }

                }
                catch (Exception exception)
                {
                    var baseException = exception.GetBaseException();
                    MessageBox.Show("Error\n\n" + exception.Message + "\n\n" + baseException.Message);
                }

            });
        if (Settings != null)
        {
            Settings.Hotlist.Clear();
            foreach (var hotItem in hotItems)
            {
                Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => Settings.Hotlist.Add(hotItem)));
            }
        }
    }

为什么RetrieveHotlist方法锁定我的UI? 为什么还要等待Task.Factory.StartNew()呢?

感谢帮助 :)

编辑:

我删除了一些代码以使其更加清晰。

private void RetrieveHotlist(object sender, RoutedEventArgs e) //button click
    {
        var b = new BackgroundWorker();
        b.DoWork += (o, args) =>
            {
                Thread.Sleep(2000); //**UI IS FULL RESPONSIVE FOR 2 sec.**
                var hotItems = new ObservableCollection<HotItem>();
                try
                {

                    var serv = "xxxx";
                    var dataModel = new xxxxDataModel(connStr);
                    var c = dataModel.SpecialNumberCategory; //**UI FREEZE / ENTITY FRAMEWORK**


        b.RunWorkerCompleted += (o, args) =>
            {

            };
        b.RunWorkerAsync();

    }

EDIT2:谢谢大家的帮助,Entity Framework导致了问题(我现在不知道为什么)。

我用SqlConnection和SqlCommand替换了所有模型行。

与UI相关的代码应在UI线程上调用。 不要将此与用于处理数据(发送,检索,更新等)的同一线程混在一起,以免发生死锁。 在您的情况下,这是由与数据库的交互引起的。

这是一个例子:

 Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => { 
    /* Your code here */ 
    MessageBox.Show("Error\n\n" + exception.Message + "\n\n" + baseException.Message);
}));

您的方法RetrieveHotlist()阻止了UI原因,代码如下

           foreach (var hotItem in hotItems)
            {
                Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => Settings.Hotlist.Add(hotItem)));
            }

在主Thread上执行。 如果您发现问题很严重,那一定是您正在将一个项目一个一个地添加到list并且每次将一个项目添加到Hotlist它都必须引起对UI的更改,即使在每次添加项目时都没有这样做,迭代一个collection并将项目添加到另一个collection需要花费一些时间,这就是UI线程的冻结时间。

为避免这种情况,您可以直接将hotItems分配给Hotlist (通过使用相应的Ienumerable转换)。 如果您可以给我提供Hotlist类型,可以给您确切的语法。 或者,您可以先准备兼容类型的临时集合,然后将该集合分配给Hotlist 关键是尽量减少UI线程的工作。 替换整个foreach ,如下所示:

Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => Settings.Hotlist.AddRange(hotItems)));

并在Thread移动由foreach完成的工作。 现在在Action ,使用AddRange() ,执行assignment或任何使其有效的工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM