需求:在silverlight用户界面上使用计时器定时刷新数据。

在 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 = ; public MainPageViewModel()
{
client = new WcfService.Service1Client();
timer = new DispatcherTimer();
timer.Interval = new System.TimeSpan(, , 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到底执行了几次。

心得:每次遇到问题,不要急躁,可以由复杂到简单,若不知问题在哪可使用排除法将问题逐一排除,最后查找到问题所在,仔细分析,不断调试,找到问题根本,得到解决。

完!

在Silverlight中的DispatcherTimer的Tick中使用基于事件的异步请求的更多相关文章

  1. C#中的异步调用及异步设计模式(三)——基于事件的异步模式

    四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: ·                 ...

  2. C#中的异步调用及异步设计模式(二)——基于 IAsyncResult 的异步设计模式

    三.基于 IAsyncResult 的异步设计模式(设计层面) IAsyncResult 异步设计模式通过名为 BeginOperationName 和 EndOperationName 的两个方法来 ...

  3. CAT中实现异步请求的调用链查看

    CAT简介 CAT(Central Application Tracking),是美团点评基于 Java 开发的一套开源的分布式实时监控系统.美团点评基础架构部希望在基础存储.高性能通信.大规模在线访 ...

  4. wpf中应该使用c#四种定时器中的DispatcherTimer

    c#中有四种定时器 1:System.Threading.Timer 使用: private System.Threading.Timer timerClose; timerClose = new S ...

  5. 地图四叉树一般用在GIS中,在游戏寻路中2D游戏中一般用2维数组就够了

    地图四叉树一般用在GIS中,在游戏寻路中2D游戏中一般用2维数组就够了 四叉树对于区域查询,效率比较高. 原理图

  6. sqlserver 中数据导入到mysql中的方法以及注意事项

    数据导入从sql server 到mysql (将数据以文本格式从sqlserver中导出,注意编码格式,再将文本文件导入mysql中): 1.若从slqserver中导出的表中不包含中文采用: bc ...

  7. 在Myeclipse中提交代码到GitHub中

    这需要借助插件Egit,首先就是先下载该插件了,可以再eclipse中下载,也可以在外面下载,下载就不说了.下载地址git://github.com/houyongchao/plugin-Egit.g ...

  8. JQuery中使用Ajax实现诸如登录名检测等异步请求Demo

    上一篇博客介绍了注册登录时一次性图形验证码的工具类的编写,这篇随笔同样是我在写用jquery中ajax实现登录信息检测的异步请求功能的笔记,在各个网站进行信息用户注册时,需要在不刷新页面的情况下对注册 ...

  9. AGS中通过FeatureServer插入数据失败、插入数据在WMTS请求中无法显示以及version概念的讨论

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 在多个项目中,当我方接口给其他部门人员使用时出现了插入数据失 ...

随机推荐

  1. CSS控制 table 的 cellpadding,cellspacing

    CSS 常规解决办法: 表格的 cellpadding 和 cellspacing 我们经常会用如下的方式来清除默认样式: <table cellspacing="0" ce ...

  2. Notepad++ 运行脚本快捷键设置

    php:cmd /k /path/to/php.exe "$(FULL_CURRENT_PATH)" & ECHO. & PAUSE & EXIT pyth ...

  3. 运用百度开放平台接口根据ip地址获取位置

    使用百度开放平台接口根据ip地址获取位置 今天无意间发现在百度开放平台接口,就把一段代码拿了下来,有需要的可以试试看:http://opendata.baidu.com/api.php?query=5 ...

  4. Java单例模式--------懒汉式和饿汉式

    单件模式用途:单件模式属于工厂模式的特例,只是它不需要输入参数并且始终返回同一对象的引用.单件模式能够保证某一类型对象在系统中的唯一性,即某类在系统中只有一个实例.它的用途十分广泛,打个比方,我们开发 ...

  5. JavaScript之this,new,delete,call,apply

    OS:Window 8.1 关键字:JavaScript,HTML,this,new,delete,call,apply. 1.this 一般而言,在Javascript中,this指向函数执行时的当 ...

  6. Python的文件与文件夹操作

    Python的文件与文件夹操作 Python OS模块 1.重命名:os.rename(old, new) 2.删除:os.remove(file) 3.列出目录下的文件 :os.listdir(pa ...

  7. 【转】C#路径/文件/目录/I/O常见操作汇总

    文件操作是程序中非常基础和重要的内容,而路径.文件.目录以及I/O都是在进行文件操作时的常见主题,这里想把这些常见的问题作个总结,对于每个问题,尽量提供一些解决方案,即使没有你想要的答案,也希望能提供 ...

  8. IOS平台汉字转拼音方案

    iOS/Mac OS X 汉字转拼音 网络流行的汉字转拼音方案是带一个拼音码表,速度快.其实Core Foundation也提供了一种方案,而且还带声调! NSMutableString *ms =  ...

  9. 使用pd设计表的 多对多的中间表的设计方式, 有图有真相

    设计多对多表时解决重复问题 目前流行两种设计方式: 方式一 是在中间表中建一个单独的id主键, 与业务表关联的键设置为unique唯一; 干事二: 联合主键的方式, 该方式中间表不会有与业务表无关的主 ...

  10. 去掉url后面的#

    <a href="#" 这个代码,当你点击后会在url后面添加# 怎么去掉呢?解决方法:点击这里 <a href="javascript:void(0)&qu ...