首页 新闻 会员 周边 捐助

关于wpf异步刷新UI的问题

0
悬赏园豆:15 [已解决问题] 解决于 2017-01-19 16:07

目前我是这么做的,利用TextBlock.Dispatcher.Invoke的方法来更新wpf界面。

但是目前执行以后,整个界面是在输出,但是会没法切换到显示上,假死状态。我试过在递归代码返回以后执行线程沉睡,但是也没有什么用处。

 

  1  private static long CurrentCheckUserId = 0;
  2         private void BtnCheckAll_Click(object sender, RoutedEventArgs e)
  3         {
  4             var dialogResult = MessageBox.Show(this, "全库检索是一个非常耗费资源和时间的操作,是否确认继续,继续请选择“确认”,否则请取消", "重要操作提示!",
  5                 MessageBoxButton.OKCancel, MessageBoxImage.Asterisk);
  6             if (dialogResult == MessageBoxResult.OK)
  7             {
  8                 LbResult.Visibility = Visibility.Collapsed;
  9                 TbInfo.Visibility= Visibility.Visible;
 10                 Task.Run(async () =>
 11                 {
 12                     Members = await _context.Members.ToListAsync();
 13                     var totalCount = Members.Count(x => x.CrmId > 1);
 14                     DispatchUpdateUi($"【{DateTime.Now:MM-dd HH:mm:ss:fff}】有上级推荐人的总用户数为:{totalCount}{Environment.NewLine}",false);
 15                     foreach (var user in Members)
 16                     {
 17                         var userId = user.Id;
 18                         CurrentCheckUserId = userId;
 19                         if (DoSearchUser(user) == 0)
 20                         {
 21                             string crmIds = string.Empty;
 22                             if (CrmIds.Count > 0)
 23                             {
 24                                 crmIds = string.Join(",", CrmIds.ToArray());
 25                             }
 26                             else
 27                             {
 28                                 crmIds = "0";
 29                             }
 30                             if (DateTime.Now.Second == 30)
 31                             {
 32                                 Thread.Sleep(1000);//每59秒休息一秒钟
 33                             }
 34                             //把获取的推荐人列表存入数据库
 35                             CrmIds.Clear();
 36                         }
 37                     }
 38                 });
 39             }
 40         }
 41 
 42         private static List<Member> Members=null;
 43         private static readonly List<long> CrmIds = new List<long>();
 44         private static readonly ILog Logger = log4net.LogManager.GetLogger("CrmIdsLog");
 45 
 46         private static string _message = null;
 47 
 48         private void DispatchUpdateUi(string sdr,bool isError=true)
 49         {
 50             try
 51             {
 52                 if (isError)
 53                 {
 54                     Logger.Error(sdr
 55                                  + Environment.NewLine
 56                                  +
 57                                  $"【{DateTime.Now:MM-dd HH:mm:ss:fff}】当前正在检查用户:{CurrentCheckUserId},目前获取的上级推荐人列表为: {string.Join(",", CrmIds.ToArray())}{Environment.NewLine}");
 58                 }
 59                 _message = sdr;
 60                 TbInfo.Dispatcher.Invoke(new UpdatetbxMessageDelegate(UpdatetbxMessageAction));
 61             }
 62             catch (Exception ex)
 63             {
 64                 throw ex;
 65             }
 66         }
 67         private delegate void UpdatetbxMessageDelegate();
 68         private void UpdatetbxMessageAction()
 69         {
 70             if (!string.IsNullOrWhiteSpace(_message))
 71             {
 72                 TbInfo.Inlines.Add(_message);
 73                 TbInfo.Inlines.Add(new LineBreak());
 74                 if (CurrentCheckUserId > 0)
 75                 {
 76                     TbInfo.Inlines.Add(
 77                         $"【{DateTime.Now:MM-dd HH:mm:ss:fff}】当前正在检查用户:{CurrentCheckUserId},目前获取的上级推荐人列表为: {string.Join(",", CrmIds.ToArray())}");
 78                     TbInfo.Inlines.Add(new LineBreak());
 79                 }
 80                 _message = null;
 81             }
 82         }
 83 
 84         private long DoSearchUser(Member member)
 85         {
 86             var userId = member.Id;
 87             if (member.CrmId == 0|| member.CrmId == 1)
 88             {
 89                 DispatchUpdateUi($"【{DateTime.Now:MM-dd HH:mm:ss:fff}】检查完成{Environment.NewLine}",false);
 90                 return 0;
 91             }
 92             if (CrmIds.Contains(member.CrmId))
 93             {
 94                 CrmIds.Add(member.CrmId);
 95                 DispatchUpdateUi($"【{DateTime.Now:MM-dd HH:mm:ss:fff}】上级推荐人列表重复:{string.Join(",", CrmIds.ToArray())}");
 96                 return 0;
 97             }
 98             CrmIds.Add(member.CrmId);
 99             //根据上级用户查询用户,然后再查询该上级用户的推荐人
100             var newmember = Members.Find(x => x.Id == member.CrmId);
101             if (newmember == null)
102             {
103                 DispatchUpdateUi($"【{DateTime.Now:MM-dd HH:mm:ss:fff}】上级推荐人ID有误:{userId},使用的上级id为{member.CrmId}");
104                 return 0;
105             }
106             return DoSearchUser(newmember);
107         }

 

 

问题补充:

。。。。是因为频繁更新的问题么?

心雨纷扬的主页 心雨纷扬 | 菜鸟二级 | 园豆:309
提问于:2017-01-13 09:51
< >
分享
最佳答案
0

不要用控件的inkove,用主线程刷新UI,控件的task.run启动后会锁死UI,鼠标没法点,但是更新看得见


收获园豆:15
秋叶无痕 | 初学一级 |园豆:26 | 2017-01-16 12:53

应该怎么处理呢?

心雨纷扬 | 园豆:309 (菜鸟二级) | 2017-01-17 15:47

@心雨纷扬: 用SynchronizationContext 试试

http://www.cnblogs.com/Kevin-moon/archive/2009/01/13/1374353.html

或者用this.Invoke 别用控件的Invoke 用主线程form的

秋叶无痕 | 园豆:26 (初学一级) | 2017-01-19 02:34

@寒叶: 用主线程的是可用的。

心雨纷扬 | 园豆:309 (菜鸟二级) | 2017-01-19 16:07
其他回答(1)
0

是的。


大概看了下,你的后台线程不停的去处理前端(这和本身的分线程是相违背的),但是你又想不停的改变前端,你应当适当时机去处理前端。本身wpf就非常庞大,效率低下,就比如你用网页处理 很多 dom一回事 ,如果确实要实时性非常强那么技术线路就不是用他。

 

补充 —— 你的代码是想写得高级漂亮,却写得还比较啰嗦。

花飘水流兮 | 园豆:13615 (专家六级) | 2017-01-13 17:50

是有个地方啰嗦些,没有优化。

 

其实这个也准备放弃了,才六万数据,等待遍历时间就几个小时也完成不来,这个递归为何耗时如此之久~~

支持(0) 反对(0) 心雨纷扬 | 园豆:309 (菜鸟二级) | 2017-01-14 09:19

@心雨纷扬: 那就可能出现回环调用了三。

支持(0) 反对(0) 花飘水流兮 | 园豆:13615 (专家六级) | 2017-01-14 14:42
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册