很多时候我们需要做一个工作,在一个方法体里面,读取大数据绑定到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. 深度学习入门教程UFLDL学习实验笔记一:稀疏自编码器

    UFLDL即(unsupervised feature learning & deep learning).这是斯坦福网站上的一篇经典教程.顾名思义,你将在这篇这篇文章中学习到无监督特征学习和 ...

  2. php获取网页内容方法总结

    抓取到的内容在通过正则表达式做一下过滤就得到了你想要的内容,至于如何用正则表达式过滤,在这里就不做介绍了,有兴趣的,以下就是几种常用的用php抓取网页中的内容的方法. 1.file_get_conte ...

  3. maven3 junit4 spring3 jdk8 :junit一直报错,害的我几个星期都是这个错,你妹的!

    [org.springframework.test.context.junit4.SpringJUnit4ClassRunner]SpringJUnit4ClassRunner constructor ...

  4. MySQL数据库备份和还原的常用命令

    其实很多情况下mysql备份就是采用了这些命令,例如: mysql导入和导出数据 linux自动定时备份web程序和mysql数据库 备份MySQL数据库的命令 mysqldump -hhostnam ...

  5. PHP+redis实现超迷你全文检索

    2014年10月31日 11:45:39 情景: 我们平台有好多游戏, 运营的同事在查询某一款游戏的时候, 目前使用的是html的select下拉列表的展现形式, 运营的同事得一个个去找,然后选中,耗 ...

  6. 理解和解决MySQL乱码问题

    本文将详细介绍MySQL乱码的成因和具体的解决方案 在阅读本文之前,强烈建议对字符集编码概念还比较模糊的同学 阅读下博主之前对相关概念的一篇科普:十分钟搞清字符集和字符编码 MySQL出现乱码的原因 ...

  7. 转MYSQL学习(三) 函数

    这一节主要介绍MYSQL里的函数,MYSQL里的函数很多,我这里主要介绍MYSQL里有而SQLSERVER没有的函数 数学函数 1.求余函数MOD(X,Y) MOD(X,Y)返回x被y除后的余数,MO ...

  8. ini 文件操作记要(1): 使用 TIniFile

    ini 文件操作记要(1): 使用 TIniFile unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Class ...

  9. Java for LeetCode 067 Add Binary

    Given two binary strings, return their sum (also a binary string). For example, a = "11" b ...

  10. Nginx(PHP/fastcgi)的PATH_INFO问题

    引用: http://www.laruence.com/2009/11/13/1138.html server { listen 80; server_name localhost; index in ...