WPF MVVM模式下的无阻塞刷新探讨
很多时候我们需要做一个工作,在一个方法体里面,读取大数据绑定到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模式下的无阻塞刷新探讨的更多相关文章
- wpf mvvm模式下CommandParameter传递多参
原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递多参数,就要稍微处理一下.我暂时还没找到更好的方案,下面介绍的这 ...
- WPF MVVM模式下ComboBox级联效果 选择第一项
MVVM模式下做的省市区的级联效果.通过改变ComboBox执行命令改变市,区. 解决主要问题就是默认选中第一项 1.首先要定义一个属性,继承自INotifyPropertyChanged接口.我这里 ...
- WPF MVVM模式下路由事件
一,路由事件下三种路由策略: 1 冒泡:由事件源向上传递一直到根元素.2直接:只有事件源才有机会响应事件.3隧道:从元素树的根部调用事件处理程序并依次向下深入直到事件源.一般情况下,WPF提供的输入事 ...
- WPF MVVM模式下实现ListView下拉显示更多内容
在手机App中,如果有一个展示信息的列表,通常会展示很少一部分,当用户滑动到列表底部时,再加载更多内容.这样有两个好处,提高程序性能,减少网络流量.这篇博客中,将介绍如何在WPF ListView中实 ...
- wpf mvvm模式下 在ViewModel关闭view
本文只是博主用来记录笔记,误喷 使用到到了MVVM中消息通知功能 第一步:在需要关闭窗体中注册消息 public UserView() { this.DataContext = new UserVie ...
- wpf mvvm模式下的image绑定
view文件 <Image Grid.Column="2" Width="48" Height="64" Stretch=" ...
- WPF中在MVVM模式下,后台绑定ListCollectionView事件触发问题
问题:WPF中MVVM模式下 ListView绑定ListCollectionView时,CurrentChanged无法触发 解决方案: 初期方案:利用ListView的SelectionChang ...
- WPF实战案例-MVVM模式下在Xaml中弹出窗体
相信很多学习和开发wpf项目的同学都了解过mvvm模式,同样,在mvvm模式下会有一个不可忽视的问题,就是怎么在xaml中弹出窗体,而不破坏MVVM本身的结构. 关于弹出窗体的方式还是很多的,本文先讲 ...
- MVVM模式下WPF动态绑定展示图片
MVVM模式下WPF动态展示图片,界面选择图标,复制到项目中固定目录下面,保存到数据库的是相对路径,再次读取的时候是根据数据库的相对路径去获取项目中绝对路径的图片展示. 首先在ViewModel中 / ...
随机推荐
- smb
smb编辑 SMB(Server Message Block)是协议名,它能被用于Wap连接和客户端与服务器之间的信息沟通.
- unity3d进行脚本资源打包加载
原地址:http://www.cnblogs.com/hisiqi/p/3204752.html 本文记录如何通过unity3d进行脚本资源打包加载 1.创建TestDll.cs文件 public c ...
- Kruskal vs Borůvka
做了个对比.Borůvka算法对于稠密图效果特别好.这两个都是求生成森林的算法.Prim+heap+tarjan过于难写不写了. V=200,E=1000 Kruskal method 4875048 ...
- 【Other】推荐点好听的钢琴曲
2013-12-13 16:19 匿名 | 浏览 138977 次 音乐钢琴 推荐点好听的钢琴曲,纯音乐也可以thanks!!! 2013-12-14 19:34 网友采纳 热心网友 巴洛克:帕海贝尔 ...
- Maximum Gap
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
- Linux set env export declare unset
http://www.it165.net/os/html/201405/8390.html env /etc/profile 环境变量 系统提供 可改 set /etc/bashrc及用户自定义的变量 ...
- java 和 objective-c 动态获得类型信息
详细信息,请参看android官方文档中的class类的介绍 ,和苹果的官方文档Objective-C Runtime Reference java中常常听到反射reflection,在java的cl ...
- (转)SQL SERVER的锁机制(二)——概述(锁的兼容性与可以锁定的资源)
二.完整的锁兼容性矩阵(见下图) 对上图的是代码说明:见下图. 三.下表列出了数据库引擎可以锁定的资源. 名称 资源 缩写 编码 呈现锁定时,描述该资源的方式 说明 数据行 RID RID 9 文件编 ...
- sqlserver的执行计划
一:执行计划生成过程 说到执行计划,首先要知道的是执行计划大概生成的过程,这样就可以做到就心中有数了,下面我画下简图: 1. 分析过程 这三个比较容易理解,首先我们要保证sql的语法不能错误,sele ...
- 写了一个字符串的二维表: TSta
STA 单元 (用到 System.SysUtils.TStringHelper): --------------------------------------------------------- ...