简洁流畅,快速响应是Windows Phone的特点也是他的买点,我们在开发App时候,也要在手机有限的硬件性能上最大限度做到UI快速响应,微软在优化手机快速响应这块做了很多底层优化工作,其中有一个就是我们要讨论的Composite Thread。

Composite Thread这个中文叫组合线程也有翻译叫构图线程。很多人对Composite Thread都并不了解,也不知道这是干什么的,因为毕竟有关Composite Thread的有关资料确实很少,而且Composite Thread最早不是在WPF/Silverlight上实现的,而是首先在Silverlight For Windows Phone 7上实现的,等到Silverlight5才引进Composite Thread。

说了那么多,那Composite Thread到底是可以用来干嘛用的,一言以蔽之就是,可以把动画剥离开UI线程到组合线程上执行。

在WP7开发中,我们如果用让用户等待一个耗时操作的完成,会用一个ProgressBar控件来提示让用户等待流程的完成。但ProgressBar有一个很不好的地方就是他是在UI线程上执行的,如果这个时候UI线程大量计算操作时候,ProgressBar就会卡成白痴(注:WP8的ProgressBar没有这个问题)。这个时候,一个叫做PerformanceProgressBar控件就闪亮登场出来救场了,PerformanceProgressBar很对得起它的Performance的Title,因为他可以做到不卡UI线程。

可能大家很好奇,因为我们知道一般更改UI操作只能是在UI线程上进行,而动画也是在更改UI,但PerformanceProgressBar却可以在非UI线程上执行动画。PerformanceProgressBar是Silverlight For WP Toolkit下一个开源控件,我们可以直接通过源码来看到他的具体实现。

通过源码我们可以看到PerformanceProgressBar仅仅只是在ProgressBar的基础上重新定制了他的Style

<PerformanceProgressBar
x:Name="customIndeterminateProgressBar"
IsIndeterminate="true"
Style="{StaticResource CustomIndeterminateProgressBar}"
/>
<Style x:Key="CustomIndeterminateProgressBar" TargetType="ProgressBar">
<Setter Property="Foreground" Value="{StaticResource PhoneAccentBrush}"/>
<Setter Property="Background" Value="{StaticResource PhoneAccentBrush}"/>
<Setter Property="Maximum" Value="100"/>
<Setter Property="IsHitTestVisible" Value="False"/>
<Setter Property="Padding" Value="{StaticResource PhoneHorizontalMargin}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<unsupported:RelativeAnimatingContentControl HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<unsupported:RelativeAnimatingContentControl.Resources>
<ExponentialEase EasingMode="EaseOut" Exponent="1" x:Key="ProgressBarEaseOut"/>
<ExponentialEase EasingMode="EaseOut" Exponent="1" x:Key="ProgressBarEaseIn"/>
</unsupported:RelativeAnimatingContentControl.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate"/>
<VisualState x:Name="Indeterminate">
<Storyboard RepeatBehavior="Forever" Duration="00:00:04.4">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="IndeterminateRoot">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DeterminateRoot">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.0" Storyboard.TargetProperty="X" Storyboard.TargetName="R1TT">
<LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
<LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.2" Storyboard.TargetProperty="X" Storyboard.TargetName="R2TT">
<LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
<LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4" Storyboard.TargetProperty="X" Storyboard.TargetName="R3TT">
<LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
<LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.6" Storyboard.TargetProperty="X" Storyboard.TargetName="R4TT">
<LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
<LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.8" Storyboard.TargetProperty="X" Storyboard.TargetName="R5TT">
<LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
<LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R1">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R2">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R3">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.6" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R4">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.8" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R5">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid x:Name="DeterminateRoot" Margin="{TemplateBinding Padding}" Visibility="Visible">
<Rectangle x:Name="ProgressBarTrack" Fill="{TemplateBinding Background}" Height="4" Opacity="0.1"/>
<Rectangle x:Name="ProgressBarIndicator" Fill="{TemplateBinding Foreground}" HorizontalAlignment="Left" Height="4"/>
</Grid>
<Border x:Name="IndeterminateRoot" Margin="{TemplateBinding Padding}" Visibility="Collapsed">
<Grid HorizontalAlignment="Left">
<Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R1" Opacity="0" CacheMode="BitmapCache">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="R1TT"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R2" Opacity="0" CacheMode="BitmapCache">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="R2TT"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R3" Opacity="0" CacheMode="BitmapCache">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="R3TT"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R4" Opacity="0" CacheMode="BitmapCache">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="R4TT"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R5" Opacity="0" CacheMode="BitmapCache">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="R5TT"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
</Border>
</Grid>
</unsupported:RelativeAnimatingContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

在上面的Style里,ProgressBar的进度动画被封装在VisualStateGroup里,动画类型是DoubleAnimation,凡是DoubleAnimation的动画都会自动在Composite Thread上执行,从而做到不卡UI线程,Silverlight的动画就是在一个时间轴上不停改变依赖属性的值,也就是只要是动画Double类型的依赖属性(比如动画TranslateTransform X Y的值,动画UI的Opacity透明度),那么这些动画都会转到Composite Thread上执行。

总结

Composite Thread的存在是为了从UI线程剥离DoubleAnimation动画出来,提高UI快速响应能力。

DoubleAnima类型的动画会自动在Composite Thread上运行。

开发WP7时候,要用Toolkit下的PerformanceProgressBar替代系统的自带的ProgressBar来获得更好的UI体验。

Windows Phone零距离开发(Composite Thread组合线程)的更多相关文章

  1. 转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。

    原文来自于:http://www.ituring.com.cn/article/128439 Windows下的PHP开发环境搭建——PHP线程安全与非线程安全.Apache版本选择,及详解五种运行模 ...

  2. Windows 平台做 Python 开发的最佳组合

    在 Windows 上怎样做 Python 开发?是像大神那样使用纯文本编辑器,还是用更加完善的 IDE?到底是用自带的命令行工具,还是需要装新的 Terminal?本文将带你了解如何利用微软官方维护 ...

  3. Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。

    今天为在Windows下建立PHP开发环境,在考虑下载何种PHP版本时,遭遇一些让我困惑的情况,为了解决这些困惑,不出意料地牵扯出更多让我困惑的问题. 为了将这些困惑一网打尽,我花了一下午加一晚上的时 ...

  4. 《深入浅出Windows 10通用应用开发》

        <深入浅出Windows 10通用应用开发>采用Windows 10的SDK进行重新改版,整合了<深入浅出Windows Phone 8.1应用开发>和<深入解析 ...

  5. windows环境下Eclipse开发MapReduce程序遇到的四个问题及解决办法

    按此文章<Hadoop集群(第7期)_Eclipse开发环境设置>进行MapReduce开发环境搭建的过程中遇到一些问题,饶了一些弯路,解决办法记录在此: 文档目的: 记录windows环 ...

  6. 【翻译习作】 Windows Workflow Foundation程序开发-第一章05

    1.3      开发我们的第一个工作流 也许你曾经在这样的产品经理手下搞过开发:他总是在你身边转悠,并不时的问一句“你还没做完吗?”.在这一部分,我们将用一个简单的Windows Workflow程 ...

  7. 【翻译习作】 Windows Workflow Foundation程序开发-前言

    Windows Workflow Foundation程序开发-基于XAML和C#的WF实战技术与例程 ——C#程序员的WF功能与编程接口技术指导 前言 Windows Workflow Founda ...

  8. 《Windows编程零基础学》第零节

    首先很开心申请到了这一个专栏<Windows编程零基础学> 这是第一篇文章,在这里,我将讲述一些基础的知识. 什么是Windows编程 所谓Windows编程就是在Windows平台上开发 ...

  9. Windows Phone 8初学者开发—第4部分:XAML简介

    原文  Windows Phone 8初学者开发—第4部分:XAML简介 原文地址: http://channel9.msdn.com/Series/Windows-Phone-8-Developme ...

随机推荐

  1. CAP原则(CAP定理)

    CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性). Availability(可用性).Partition tolerance(分区容错性),三者不可得兼. CA ...

  2. 保持UIImagePickerController后导航栏风格统一

    1. UIImagePickerController 状态栏始终保持某一种风格. -(void)navigationController:(UINavigationController *)navig ...

  3. vacabulary1

    The hard hat is rigid,so nothing will hurt my head. glue 胶水vegetarian 素食者: 素食主义者:素食的 North Korea 朝鲜S ...

  4. JS 中的 Window 对象

    窗口对象的属性和方法: 在js最外层写的function可以还可以理解为window对象的一个方法.定义的变量也可以称之为window对象的一个属性.例如:window.alert("--- ...

  5. compass项目监控文件报 /usr/bin/env 找不到文件

    1 找到ruby执行文件目录 $ wherris ruby ruby: /usr/lib/ruby /home/rudy/.rbenv/shims/ruby 2 设置软链接 sudo ln -s /h ...

  6. gulp构建前端开发环境

    1.gulp环境的安装 首先确保你已经正确安装了nodejs环境.然后以全局方式安装gulp: npm install -g gulp 2.建立文件夹 mkdir item 3.初始化项目: npm ...

  7. jsp标准标签库

    抄袭自:http://www.cnblogs.com/hongten/archive/2011/05/14/2046005.html JSP标准标签库     Pass by xkk ,and aut ...

  8. 山东省第四届ACM省赛

    排名:http://acm.sdut.edu.cn/sd2012/2013.htm 解题报告:http://www.tuicool.com/articles/FnEZJb A.Rescue The P ...

  9. mysql start server faild

    可能没卸载干净...在安装mysql数据库时,如果重新安装,很容易遇见apply security setting error,即在配置mysql启动服务时,在启动apply security set ...

  10. .NET基础操作回顾_使用ADO.NET操作SqlServer使用的类

    有些工具用的久了或者有新工具出现后,就慢慢的遗忘了很多,它们从熟悉的变成陌生,当然,对于我们来说不是好事吧. 今天回顾一下ADO.NET用到的MS的基础类库,先上代码(标准的SqlServer操作) ...