linux社区爱心援助Linux认证系列教程业界动态站务新闻公司招聘网络学院网址大全LPI专题CISCO专题
设为首页
加入收藏
管理团队
JSP  
JAVA  
PERL  
 您的位置:首页 > 开发语言 > asp.net >
栏目导栏
  php
  JSP
  ASP
  asp.net
  JAVA
  c/c++/c#
  perl
  JavaScript
  Basic
  Delphi
资料搜索
热门文章
·NetBPM工作流的一个示例:请假
·Office Web Components(OWC)绘
·asp.net正则表达式语法
·asp.net 2.0 ajax中使用PopupC
·Ado.Net读取Excel常见问题总结
·数据源为空时如何让GridView显
·如何让UpdatePanel支持文件上传
·C#.Net的常见面试试题和参考答
·asp.net ajax客户端编程+jquer
·Brettle.Web.NeatUpload.dll支
·ASP.NET使用Cookie
·ASP.NET DEMO 15: 同时支持行单
·如何使IE的后退按钮无效
·如何在ASP.NET中用OWC绘制图表
·asp.net:正确判断当前用户角色
最新文章
·Ajax Control Toolkit Animati
·讨论一下类似BlogEngine内一次
·使用CSS+SiteMap+UserControl+
·Asp.net中多彩下拉框的实现
·浅谈ASP.NET的Postback
·分清ASP.NET AJAX中的Extender
·Tip:在使用AjaxControlTookit
·有关注册DataItem的一些可能被
·IIRF(Ionic's Isapi Rewrite
·asp.net 客户端回调功能的实现
·关于控件部分的看法--读Progra
·为什么在vista上做开发
·如何封装JS和CSS文件为服务器端
·岂今我看过的最强的排序算法
·设计模式学习笔记之单件模式
Google
 
大数据量填充UI的技巧
[ 作者:  加入时间:2007-10-29 14:12:33  来自:Linux联盟收集整理 ]
这个内容本来已经在我过去的一篇随笔中略有提及,但是没有详细的说明这个问题。今天我就这个问题详细的讨论一下。这个问题的提出其实是一个源于一个设计缺陷或者错误。我所在的公司开发了一个财务系统,这个系统中有一张报表,这个报表的主要功能是显示数据检索的结果。由于在设计之初没有考虑分页处理,所以导致客户没有输入检索条件的时候,需要在界面上显示几万到几十万条记录。由于数据量非常大,导致UI的填充时间非常的漫长,为了提高UI填充的速度,采用了异步处理的方式,最初的处理方式如下: NrELinux联盟
   1 '数据传送事件 NrELinux联盟
   2 Sub DataRowTransport(ByVal sender As Object, ByVal e As DataRowTransportEventArgs) NrELinux联盟
   3 NrELinux联盟
   4 '判断是否要进行线程调度 NrELinux联盟
   5 If Me.InvokeRequired Then NrELinux联盟
   6 NrELinux联盟
   7 '调度线程 NrELinux联盟
   8 Me.BeginInvoke(New DataRowTransportHandler(AddressOf DataRowTransport), New Object() {sender, e}) NrELinux联盟
   9 Else NrELinux联盟
  10 NrELinux联盟
  11 '将数据填充到Grid NrELinux联盟
  12 Me.FillGrid(e.Data) NrELinux联盟
  13 NrELinux联盟
  14 '响应事件处理 NrELinux联盟
  15 Application.DoEvents() NrELinux联盟
  16 NrELinux联盟
  17 '判断是否退出 NrELinux联盟
  18 If Me.Cancel Then NrELinux联盟
  19 NrELinux联盟
  20 e.Cancel = True NrELinux联盟
  21 End If NrELinux联盟
  22 End If NrELinux联盟
  23 End Sub 从代码的角度来看这段代码是没有什么问题的,基本上是微软提出的线程调度的最佳实践了,但是在实际中运用效果很不理想:界面不能刷新也不能响应取消操作(用户可以选择取消填充)。其实仔细想一想也不难明白,由于数据量很大,导致调用BeginInvoke的调用次数很大,而且两次之间的调用间隔很短,基本上把UI线程的消息循环给填满了,几乎没有机会来响应界面的操作了。 NrELinux联盟
  经过分析之后,发现了一个较好的解决方案,代码如下: 1 '数据缓存 NrELinux联盟
   2 Private _buffer As New ArrayList NrELinux联盟
   3 NrELinux联盟
   4 '数据填充队列 NrELinux联盟
   5 Private _dataQueue As New Queue NrELinux联盟
   6 NrELinux联盟
   7 '数据传送事件,由数据传输线程触发 NrELinux联盟
   8 Sub DataRowTransport(ByVal sender As Object, ByVal e As DataRowTransportEventArgs) NrELinux联盟
   9 NrELinux联盟
  10 '添加到缓存 NrELinux联盟
  11 Me._buffer.Add(e.Data) NrELinux联盟
  12 NrELinux联盟
  13 '判断是否需要添加到填充队列中 NrELinux联盟
  14 If Me._buffer.Count > 100 Then NrELinux联盟
  15 NrELinux联盟
  16 '锁定 NrELinux联盟
  17 SyncLock Me._dataQueue NrELinux联盟
  18 NrELinux联盟
  19 '添加到队列中 NrELinux联盟
  20 Me._dataQueue.Enqueue(Me._buffer.ToArray()) NrELinux联盟
  21 End SyncLock NrELinux联盟
  22 NrELinux联盟
  23 '清除数据 NrELinux联盟
  24 Me._buffer.Clear() NrELinux联盟
  25 End If NrELinux联盟
  26 NrELinux联盟
  27 '判断是否退出 NrELinux联盟
  28 If Me.cancel Then NrELinux联盟
  29 NrELinux联盟
  30 e.Cancel = True NrELinux联盟
  31 End If NrELinux联盟
  32 End Sub NrELinux联盟
  33 NrELinux联盟
  34 '填充数据,在UI线程调用 NrELinux联盟
  35 Sub FillData() NrELinux联盟
  36 NrELinux联盟
  37 '用于保存临时数据 NrELinux联盟
  38 Dim tempData As Object NrELinux联盟
  39 NrELinux联盟
  40 While (True) NrELinux联盟
  41 NrELinux联盟
  42 '设置数据为空 NrELinux联盟
  43 tempData = Nothing NrELinux联盟
  44 NrELinux联盟
  45 '判断是否取消 NrELinux联盟
  46 If Me.cancel Then NrELinux联盟
  47 NrELinux联盟
  48 '退出循环 NrELinux联盟
  49 Exit While NrELinux联盟
  50 End If NrELinux联盟
  51 NrELinux联盟
  52 '判断是否有数据 NrELinux联盟
  53 If Me._dataQueue.Count > 0 Then NrELinux联盟
  54 NrELinux联盟
  55 SyncLock Me._dataQueue NrELinux联盟
  56 NrELinux联盟
  57 '判断是否有数据,检查两次尽可能的避免同步线程 NrELinux联盟
  58 If Me._dataQueue.Count > 0 Then NrELinux联盟
  59 NrELinux联盟
  60 '填充界面 NrELinux联盟
  61 tempData = Me._dataQueue.Dequeue() NrELinux联盟
  62 End If NrELinux联盟
  63 NrELinux联盟
  64 End SyncLock NrELinux联盟
  65 NrELinux联盟
  66 End If NrELinux联盟
  67 NrELinux联盟
  68 '判断是否有数据 NrELinux联盟
  69 If Not tempData Is Nothing Then NrELinux联盟
  70 NrELinux联盟
  71 '填充界面 NrELinux联盟
  72 Me.FillGrid(tempData) NrELinux联盟
  73 End If NrELinux联盟
  74 NrELinux联盟
  75 '处理消息循环 NrELinux联盟
  76 Application.DoEvents() NrELinux联盟
  77 NrELinux联盟
  78 End While NrELinux联盟
  79 NrELinux联盟
  80 End Sub经过实际测试,这种解决方案几乎不会延迟数据读取线程,总的时间几乎不到第一种方案的一半,而且正常的响应UI事件。通过这个事件说明,通过BeginInvoke的方式将后台线程操作调度到UI线程其实性能是比较差的(经过实际测试使用BeginInvoke调度操作UI的耗费的时间为直接跨线程不同步的操作UI耗费时间的两倍,而直接跨线程不同步调用UI耗费的时间是在UI线程中调用同一个方法的2被),在常规情况下应用还可以,但是一旦数据量很大,或者并发非常大的情况下,就需要考虑用其它的手段来处理了 Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
无相关信息