在Silverlight中的DispatcherTimer的Tick中使用基于事件的异步请求
2015-06-30 13:45
501 查看
需求:在silverlight用户界面上使用计时器定时刷新数据。
在 Silverlight 中的 DispatcherTimer 的 Tick 事件 中使用异步请求数据时,会出现多次请求的问题,以下是ViewModel的代码,看样子没什么问题:
然而,结果并不是我们预期的那样,每次请求成功后,Count会以这样的数列进行累加:1 3 6 10 15 21 。
经调试三天,排除在View层对ViewMode进行了多次初始化使Timer多次创建实例的可能,其他各种情况都排除后,最终把问题锁定在Tick的方法体。
后来又经过再三调试,终于知道特么的问题在哪了,卧槽我艹,允许我爆一句粗口,搞了两三天,妈蛋,才发现问题这么简单,仔细观察代码,可以看出这是基于事件的异步编程模型。
问题:在Tick的方法里,client.GetDataCompleted+=((s,e)=>{//do something}); ,那么每次到了Tick执行周期的时候都会"+=" 一次事件,所以给了我们多次请求的错觉,实际是请求了一次,只是多次执行了Completed事件而已。
这就是为什么Count的结果不是我们预期的 1 2 3 4 5 6 ... ,修改的代码如下:
将Completed的事件单独提出来,在每次进入到Completed后,使用 "-=" 取消注册该事件,再次进入到Tick的时候,重新请求,重新绑定就OK了,也可以直接在ViewModel的构造函数里绑定Completed事件,每次Tick里只请求client.GetDataAsync(),不需要在进行+=client_GetDataCompleted ,两种方法皆可。
注意:实际项目中用到的是client_GetDataCompeleted事件的e.Result,这里是为了方便调试写的一个Demo,使用Count的目的是为了监测Compeleted到底执行了几次。
心得:每次遇到问题,不要急躁,可以由复杂到简单,若不知问题在哪可使用排除法将问题逐一排除,最后查找到问题所在,仔细分析,不断调试,找到问题根本,得到解决。
完!
在 Silverlight 中的 DispatcherTimer 的 Tick 事件 中使用异步请求数据时,会出现多次请求的问题,以下是ViewModel的代码,看样子没什么问题:
using System; using System.Net; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Threading; namespace AsyncTest.ViewModel { public class MainPageViewModel : NotificationBase { private int count; public int Count { get { return count; } set { this.count = value; base.OnPropertyChanged("Count"); } } protected WcfService.Service1Client client = null; private DispatcherTimer timer = null; protected int Interval = 1; public MainPageViewModel() { client = new WcfService.Service1Client(); timer = new DispatcherTimer(); timer.Interval = new System.TimeSpan(0, 0, Interval); timer.Tick += timer_Tick; timer.Start(); } private void timer_Tick(object sender, EventArgs ee) { client.GetDataAsync(); client.GetDataCompleted += ((s, e) => { this.Count++; }); } } }
然而,结果并不是我们预期的那样,每次请求成功后,Count会以这样的数列进行累加:1 3 6 10 15 21 。
经调试三天,排除在View层对ViewMode进行了多次初始化使Timer多次创建实例的可能,其他各种情况都排除后,最终把问题锁定在Tick的方法体。
后来又经过再三调试,终于知道特么的问题在哪了,卧槽我艹,允许我爆一句粗口,搞了两三天,妈蛋,才发现问题这么简单,仔细观察代码,可以看出这是基于事件的异步编程模型。
问题:在Tick的方法里,client.GetDataCompleted+=((s,e)=>{//do something}); ,那么每次到了Tick执行周期的时候都会"+=" 一次事件,所以给了我们多次请求的错觉,实际是请求了一次,只是多次执行了Completed事件而已。
这就是为什么Count的结果不是我们预期的 1 2 3 4 5 6 ... ,修改的代码如下:
private void timer_Tick(object sender, EventArgs ee) { client.GetDataAsync(); client.GetDataCompleted += client_GetDataCompleted; } void client_GetDataCompleted(object sender, WcfService.GetDataCompletedEventArgs e) { //移除该事件,防止下次Tick事件执行时再次注册 client.GetDataCompleted -= client_GetDataCompleted; this.Count++; }
将Completed的事件单独提出来,在每次进入到Completed后,使用 "-=" 取消注册该事件,再次进入到Tick的时候,重新请求,重新绑定就OK了,也可以直接在ViewModel的构造函数里绑定Completed事件,每次Tick里只请求client.GetDataAsync(),不需要在进行+=client_GetDataCompleted ,两种方法皆可。
注意:实际项目中用到的是client_GetDataCompeleted事件的e.Result,这里是为了方便调试写的一个Demo,使用Count的目的是为了监测Compeleted到底执行了几次。
心得:每次遇到问题,不要急躁,可以由复杂到简单,若不知问题在哪可使用排除法将问题逐一排除,最后查找到问题所在,仔细分析,不断调试,找到问题根本,得到解决。
完!
相关文章推荐
- Data URI scheme 实现数据的URI访问
- 16 面向对象 接口
- SQL_LINQ left join list<string>
- Maven实战(一)——坐标规划
- hiho 1182 : 欧拉路·三
- 竞价广告系统-广告网络
- tomcat,mysql,linux服务器性能调优
- Tomcat中配置JNDI数据源
- Tomcat中配置JNDI数据源
- Node.js学习开始了——事件流的控制/文件读写事件的的方法
- 版本控制git(三)-git分支
- JavaSE实战——API(上) Eclipse使用、Object、Scanner、String、StringBuffer、StringBuilder、Integer、模拟用户登录案例
- 15 面向对象 抽象类 内部类 Object类
- Apache与Nginx的优缺点比较
- PullToRefreshListView 使用 onItemLongClick 的正确打开方式
- 映射网络驱动器
- SQL SERVER ->> Columnstore Index
- 多个客户端上传文件
- java 知识点
- [Android] BroadcastReceiver - 廣播接收器