很多时候我们需要做一个工作,在一个方法体里面,读取大数据绑定到UI界面,由于长时间的读取,读取独占了线程域,导致界面一直处于假死状态。例如,当应用程序开始读取Web资源时,读取的时效是由网络链路的速度决定的,那么在读取的过程中整个程序都必然处于一种等待状态,这不是我们想要看到的。那么我们有没有一种机制既能解决效率问题同时可以提供代码的可用性呢?有人可能会说,我们可以使用线程池。线程真的是万能的吗?当处理大并发数据量时就能说明这个问题,线程池最大的并发量有限制,而且线程是极度占用资源。

.NET 4.5下提供了一种异步方式,能够有效的避免效率瓶颈并增强应用程序的可维护性,这种机制类似于Node.js原理,这是一个完全单线程的方法,当有数据传递过程时,它首先把数据交给异步处理,再完成后再通过回调返回数据集,我们可以理解为c#版的闭包。它的最大作用是把原来的等待换成异步方式,把UI解放出来,因为UI的活动都是共用一个域的。

先看看传统模式下的无阻塞刷新,首先是XAML页面文件

 <Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<ListView Grid.Row="0" Width="auto" Height="auto" Name="lvData" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListView.View>
<GridView>
<GridViewColumn Header="编号" DisplayMemberBinding="{Binding Path=Id}" Width="100" />
<GridViewColumn Header="随机数" DisplayMemberBinding="{Binding Path=Code}" Width="160"/> </GridView>
</ListView.View> </ListView> </Grid>

再新建一个ViewModel类,这个类的作用是为我们的MVVM模式提供一个数据源

 public class RandomViewModel
{
public RandomViewModel()
{
Model = new ObservableCollection<RandomData>();
} public ObservableCollection<RandomData> Model; public List<RandomData> dataList; public void FillData()
{
Model.Clear();
for (int i = ; i < dataList.Count; i++)
{
Model.Add(dataList[i]);
} } public void GetData()
{
dataList = new List<RandomData>();
Random random = new Random();
for (int i = ; i < ; i++)
{ dataList.Add(new RandomData()
{
Id = i,
Code = random.NextDouble()
});
}
}
}
public class RandomData
{
public int Id { get; set; }
public double Code { get; set; }
}

传统模式下的无刷新调用,先在线程内部计算出需要绑定的数据,然后再使用Invoke填充Model.

            Thread thread = new Thread(p =>
{
while (true)
{
ViewModel.GetData();
this.Dispatcher.Invoke(new Action<List<RandomData>>(result =>
{
ViewModel.FillData();
}), ViewModel.dataList); Thread.Sleep();
}
});
thread.IsBackground = true;
thread.Start();

在代码中嵌入线程函数,代码是很分散的,同时也消耗大量资源。为了让我们代码尽可能的做到内外同步执行。我们使用async、await、Task

  private async Task AsyncAccess()
{
while (true)
{
var getDataListTask = new Task(() =>
{
Thread.Sleep();
ViewModel.GetData();
}); getDataListTask.Start(); await getDataListTask; var fillModelTask = Task.Factory.StartNew(() =>
{
ViewModel.FillData();
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); await fillModelTask;
} }

理论上说,Task.Factory.StartNew也是在线程池上执行,可表示异步操作而且更加通用,其中在Task前加上await使用成为异步函数,不然UI界面仍会有卡顿的现象。
最后一个Invoke方法,需要通过SynchronizationContext.SetSynchronizationContext方法在多线程环境下设置SynchronizationContext.Current属性,将线程控制域转交至UI,设置当前SynchronizationContext相关的TaskScheduler,利用这个TaskScheduler,Task将通过当前SynchronizationContext来执行,实际上上述代码在WPF下等效于调用Dispatcher.BeginInvoke方法。

.net 4.5下已默认封装的相关类库有

访问Web HttpClient , SyndicationClient
使用文件 StorageFile, StreamWriter, StreamReader,XmlReader
使用图像 MediaCapture, BitmapEncoder, BitmapDecoder
WCF程序开发 Synchronous and Asynchronous Operations
使用sockets Socket

WPF MVVM模式下的无阻塞刷新探讨的更多相关文章

  1. wpf mvvm模式下CommandParameter传递多参

    原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递多参数,就要稍微处理一下.我暂时还没找到更好的方案,下面介绍的这 ...

  2. WPF MVVM模式下ComboBox级联效果 选择第一项

    MVVM模式下做的省市区的级联效果.通过改变ComboBox执行命令改变市,区. 解决主要问题就是默认选中第一项 1.首先要定义一个属性,继承自INotifyPropertyChanged接口.我这里 ...

  3. WPF MVVM模式下路由事件

    一,路由事件下三种路由策略: 1 冒泡:由事件源向上传递一直到根元素.2直接:只有事件源才有机会响应事件.3隧道:从元素树的根部调用事件处理程序并依次向下深入直到事件源.一般情况下,WPF提供的输入事 ...

  4. WPF MVVM模式下实现ListView下拉显示更多内容

    在手机App中,如果有一个展示信息的列表,通常会展示很少一部分,当用户滑动到列表底部时,再加载更多内容.这样有两个好处,提高程序性能,减少网络流量.这篇博客中,将介绍如何在WPF ListView中实 ...

  5. wpf mvvm模式下 在ViewModel关闭view

    本文只是博主用来记录笔记,误喷 使用到到了MVVM中消息通知功能 第一步:在需要关闭窗体中注册消息 public UserView() { this.DataContext = new UserVie ...

  6. wpf mvvm模式下的image绑定

    view文件 <Image Grid.Column="2" Width="48" Height="64" Stretch=" ...

  7. WPF中在MVVM模式下,后台绑定ListCollectionView事件触发问题

    问题:WPF中MVVM模式下 ListView绑定ListCollectionView时,CurrentChanged无法触发 解决方案: 初期方案:利用ListView的SelectionChang ...

  8. WPF实战案例-MVVM模式下在Xaml中弹出窗体

    相信很多学习和开发wpf项目的同学都了解过mvvm模式,同样,在mvvm模式下会有一个不可忽视的问题,就是怎么在xaml中弹出窗体,而不破坏MVVM本身的结构. 关于弹出窗体的方式还是很多的,本文先讲 ...

  9. MVVM模式下WPF动态绑定展示图片

    MVVM模式下WPF动态展示图片,界面选择图标,复制到项目中固定目录下面,保存到数据库的是相对路径,再次读取的时候是根据数据库的相对路径去获取项目中绝对路径的图片展示. 首先在ViewModel中 / ...

随机推荐

  1. 繁华模拟赛 Evensgn与字符矩阵

    #include<iostream> #include<cstdio> #include<string> #include<cstring> #incl ...

  2. Fortran向C传递NULL值

    在很多C或C++的头文件定义中,NULL被指定定义为0,这里不再具体展开 gfortran的手册关于iso c binding的章节,定义NULL如下 Moreover, the following ...

  3. zstu.4191: 无向图找环(dfs树 + 邻接表)

    4191: 无向图找环 Time Limit: 5 Sec  Memory Limit: 128 MB Submit: 117  Solved: 34 Description 给你一副无向图,每条边有 ...

  4. cocos2d回忆

    凭借自己的回忆想想看自己都学到了那些知识,这是小学的时候当初中老师的外公给我说的,现在想想,CCDirector,CCNode,CCScene,CCSprite这几个类,然后是坐标,锚点,CCNode ...

  5. HLG2081分苹果

    苹果 Time Limit: 1000 MS Memory Limit: 32768 K Total Submit: 39(24 users) Total Accepted: 29(22 users) ...

  6. 最长递增子序列问题 nyoj 17单调递增最长子序列 nyoj 79拦截导弹

    一,    最长递增子序列问题的描述 设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1< ...

  7. tornado--之cookie自定义(还有session)

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAhAAAAHzCAIAAAD+WrNvAAAgAElEQVR4nOy993cTV7/vf/6qu865ob

  8. Linux生产服务器Shell脚本分享

    Linux生产服务器Shell脚本分享 2012-6-6 86市场网 linux 作为一名Linux/unix系统管理员,我经常遇到人问这个问题:shell能做什么?PHP这么强大,为什么不用PHP来 ...

  9. python chm 中文帮助 (2.7 和 3.4)

    sphinx-build 生成的(htmlhelp) 存在2个问题 1.生成的html 编码 cp2152,需要修改/sphinx/builders/html.py ctx['encoding'] = ...

  10. JavaScript当离开页面时可以进行的操作

    当JavaScript离开页面时可以进行的操作 window.onbeforeunload = function() { var email = document.getElementById(&qu ...