反应性扩展框架(Reactive Extensions)

转载 2012年03月22日 21:48:59

    Reactive 编程模型:Reactive Extensions for .NET Framework 是一个托管库,它提供用于编写反应式应用程序的 API。反应式应用程序是由其环境驱动的。在反应式模型中,数据流、异步请求以及事件都表示为可观察序列。应用程序可以订阅这些可观察序列,以在新数据到达时接收异步消息。Reactive Extensions 允许应用程序使用查询运算符组合这些序列。如果您的应用程序与多个数据源(如用户输入事件、Web 服务请求以及系统通知)交互,则管理所有这些交互的便利方法是为每个数据流实现单独的处理程序。在这些处理程序中,您必须提供代码以在所有不同的数据流之间进行协调并将该数据处理为可使用的形式。Reactive Extensions 允许您编写一个查询,该查询将所有这些数据流组合成触发单个处理程序的单个流。筛选、同步和转换数据等工作由 Reactive Extensions 查询执行,以便您的处理程序只需对接收的数据进行反应并对该数据进行某些处理。

      下面是林永坚对反应性扩展框架的总结:

    在前一篇博文中,学习了如何使用地理位置服务(Location Service),但是在模拟器上我们无法获得相关的地理位置信息,下面用这节学习的内容模拟地理位置的数据~

MainPage.xaml代码如下:

View Code
<phone:PhoneApplicationPage 
x:Class="RecativeExtension.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="示例程序" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="反应性扩展框架" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock Height="30" HorizontalAlignment="Left" Margin="27,76,0,0" Name="textBlock1" Text="经度" VerticalAlignment="Top" />
<TextBlock Height="30" HorizontalAlignment="Left" Margin="24,153,0,0" Name="textBlock2" Text="纬度" VerticalAlignment="Top" />
<TextBox Height="72" HorizontalAlignment="Left" Margin="70,50,0,0" Name="logTxtBox" Text="" VerticalAlignment="Top" Width="460" />
<TextBox Height="72" HorizontalAlignment="Left" Margin="70,128,0,0" Name="latTxtBox" Text="" VerticalAlignment="Top" Width="460" />
<Button Content="开始" Height="72" HorizontalAlignment="Left" Margin="70,299,0,0" Name="button1" VerticalAlignment="Top" Width="160" Click="button1_Click" />
<Button Content="结束" Height="72" HorizontalAlignment="Left" Margin="248,299,0,0" Name="button2" VerticalAlignment="Top" Width="160" Click="button2_Click" />
<TextBlock Height="30" HorizontalAlignment="Left" Margin="24,230,0,0" Name="textBlock3" Text="状态" VerticalAlignment="Top" />
<TextBox Height="72" HorizontalAlignment="Left" Margin="70,206,0,0" Name="statusTxtBox" Text="" VerticalAlignment="Top" Width="460" />

</Grid>
</Grid>

<!--Sample code showing usage of ApplicationBar-->
<!--<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="MenuItem 1"/>
<shell:ApplicationBarMenuItem Text="MenuItem 2"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>-->

</phone:PhoneApplicationPage>

MainPage.xaml.cs代码如下:

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

using System.Device.Location;
using Microsoft.Phone.Reactive;
using System.Threading;

namespace RecativeExtension
{
public partial class MainPage : PhoneApplicationPage
{
GeoCoordinateWatcher watcher;
bool useEmulation = true;
// Constructor
public MainPage()
{
InitializeComponent();
}

private void StartEmulation()
{
// EmulatePositionChangedEvents returns an IEnumerable object.
// Convert this to an Observable sequence.
var position = EmulatePositionChangedEvents().ToObservable();

// Subscribe to the Observable sequence.
// Use null for the sender parameter to the event handler.
position.Subscribe(evt => watcher_PositionChanged(null, evt));
}

static IEnumerable<GeoPositionChangedEventArgs<GeoCoordinate>> EmulatePositionChangedEvents()
{
// Create a Random object to create random numbers.
Random random = new Random();

// Loop infinitely.
for (; ; )
{
// Pause for 100 milliseconds in each loop.
Thread.Sleep(random.Next(100));

// Generate a random latitude and longitude. You could also load position data from a file or
// generate the data from user input.
double latitude = (random.NextDouble() * 180.0) - 90.0; // latitude is between -90 and 90
double longitude = (random.NextDouble() * 360.0) - 180.0; // longitude is between -180 and 180

// Use yield to return a new instance of the GeoPositionChangedEventArgs class that is exposed
// through the IEnumerable interface.
yield return new GeoPositionChangedEventArgs<GeoCoordinate>(
new GeoPosition<GeoCoordinate>(DateTimeOffset.Now, new GeoCoordinate(latitude, longitude)));

}
}

// Event handler for location data. This invokes code on the
// page's main thread.
private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
Dispatcher.BeginInvoke(() =>
{
latTxtBox.Text = e.Position.Location.Latitude.ToString("0.00");
logTxtBox.Text = e.Position.Location.Longitude.ToString("0.00");
});
}

private void button1_Click(object sender, RoutedEventArgs e)
{
// First, handle the case where emulation is not being used.
if (!useEmulation)
{
// Initialize the GeoCoordinateWatcher.
watcher = new GeoCoordinateWatcher();

// Reactive Extensions uses Observable sequences to represent data streams.
// Create an Observable sequence from the event stream using the FromEvent method.
// This method uses the .NET Generic syntax to specify the type of event args for the event.
// The parameters to the method are the add and remove handlers of the GeoCoordinateWatcher object.
IObservable<IEvent<GeoPositionChangedEventArgs<GeoCoordinate>>> positionEventAsObservable =
Observable.FromEvent<GeoPositionChangedEventArgs<GeoCoordinate>>(
ev => watcher.PositionChanged += ev,
ev => watcher.PositionChanged -= ev);

// Subscribe to the observable data stream. You can use the same event handler as if you
// were using the GeoCoordinateWatcher.PositionChanged event directly.
var positionSubscription = positionEventAsObservable.Subscribe(
args => watcher_PositionChanged(args.Sender, args.EventArgs));

// Start the GeoCoordinateWatcher to begin receiving data from the Location Service.
watcher.Start();
}
else
{
// Start the thread on which emulated location data is generated.
// The method StartEmulation is defined next.
Thread emulationThread = new Thread(StartEmulation);
emulationThread.Start();
}

}

private void button2_Click(object sender, RoutedEventArgs e)
{

}
}
}

程序运行效果如下:

      关于反应性扩展框架,请参见MSDN:Windows Phone 的 Reactive Extensions for .NET Framework 概述 、How to: Use Reactive Extensions to Emulate and Filter Location Data for Windows Phone

      另外,《Windows Phone 7高级编程》P160、P168也提供了2中模拟位置的方法,个人以为比反应性扩展框架模拟的简单,感兴趣的博友可以自己学习一下~

      希望对大家有帮助~

相关文章推荐

Reactive Extensions (Rx) 入门(4) —— Rx的事件编程②

原文:http://www.atmarkit.co.jp/fdotnet/introrx/introrx_01/introrx_02_02.html作者:河合 宜文事件是什么?用Rx来处理事件的优势让...

Reactive Extensions (Rx) 拖拽实例

Rx 最大的特点就是可以对事件进行组合形成一个新的事件。比如下面的这个拖拽。我们对于拖拽的定义是:当鼠标按下时开始DragDrop,当鼠标移动时移动图形,最后当鼠标放开时停止DragDrop。我定义了...

.NET 3.5 SP1 中使用TPL --> DevLabs: Reactive Extensions for .NET (Rx)

DevLabs: Reactive Extensions for .NET (Rx)http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx Rx N...

The Reactive Extensions for JavaScript (RxJS)

Rxjs是用于Javascript的一组库,用于构成异步的、用了可观察集合的项目,及ES5的Array#extras类型。为什么需要响应式? 应用程序,特别是web上的已经因为Ajax革命,从简单的...

反应式编程(Reactive Programming)

反应式编程(Reactive Programming)这种新的编程范式越来越受到开发人员的欢迎。在 Java 社区中比较流行的是 RxJava 和 RxJava 2。本文要介绍的是另外一个新的反应式编...

.NET Reactive Extensions Fundamentals

  • 2017年10月30日 16:48
  • 48B
  • 下载

Programming Reactive Extensions and LINQ

  • 2017年04月22日 09:05
  • 6.21MB
  • 下载

Reactive Programming with RxJava-Chapter2:Reactive Extensions

Anatomy of rx.ObservableIndeed,Observablecan actually produce three types of events: Values of type ...
  • sxenon
  • sxenon
  • 2017年02月22日 13:12
  • 128

Rx(reactive extensions)demo 源代码

  • 2015年06月15日 22:36
  • 1.26MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:反应性扩展框架(Reactive Extensions)
举报原因:
原因补充:

(最多只允许输入30个字)