讓我們從頭開始:Silverlight和RX:爲什麼我必須調整瀏覽器來更新UI?
我正在爲Silverlight應用程序編寫一個算法,該算法必須通過高複雜度的許多不同組合來找到最佳值。爲了給算法提供使用客戶端上所有給定資源的可能性,我決定提供一個並行版本。
首先,我編寫了自己的異步事件驅動的調度器類,它帶有一個等待句柄和一個阻塞對象,用於限制並行線程的數量並等待最後的所有線程,直到我終止了CalculationCompletedEvent :我使用Backgroundworkers來執行多線程)。但是有些東西沒有線程安全,並且結果列表中返回元素的數量並不是恆定的。在一位同事指出我關於Reactive Extensions(rx)後,我認爲不要花費更多時間尋找泄漏。
想要知道如何使用這個,我將consumer-producer example與一些關於如何使用rx(example1和example2)的建議結合在一起。
這很好,但我不明白的是:爲什麼我必須調整瀏覽器的大小以更新列表框並顯示包含「_receivedStrings」元素?再次是一個小小的愚蠢的忽視?順便說一句:如果你不會推薦使用rx,請給我一個鏡頭,告訴我爲什麼以及使用其他方法。
XAML:
<UserControl x:Class="ReactiveTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox HorizontalAlignment="Stretch" Name="listBox1"
VerticalAlignment="Stretch" ItemsSource="{Binding}"/>
<Button Grid.Row="1" Content="Klick me!" Width="Auto" Height="Auto"
HorizontalAlignment="Center" Click="Button_Click"/>
</Grid>
</UserControl>
代碼隱藏:
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 System.IO;
using System.Reactive.Linq;
namespace ReactiveTest
{
public partial class MainPage : UserControl
{
private int _parallelThreadsAmount;
public IList<String> receivedStrings;
public MainPage()
{
InitializeComponent();
receivedStrings =
new List<String>();
this._parallelThreadsAmount = 10;
this.listBox1.DataContext = receivedStrings;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
IList<IObservable<String>> obsCollection =
new List<IObservable<String>>();
foreach (var item in forums)
{
obsCollection.Add(Calculate(item));
}
DateTime start = DateTime.Now;
obsCollection.Merge(this._parallelThreadsAmount)
.Subscribe(
y =>
{
receivedStrings.Add(
String.Format("{0} - Received: {1}", receivedStrings.Count, y));
},
() =>
{
DateTime end = DateTime.Now;
TimeSpan elapsed = end - start;
this.receivedStrings.Add(
String.Format(
"{0}/{1} done in {2} ms.",
receivedStrings.Count,
forums.Count(),
elapsed.TotalSeconds)
);
}
);
}
IObservable<String> Calculate(String source)
{
Random rand = new Random();
return Observable.Defer(() => Observable.Start(() =>
{
// simulate some work, taking different time,
// to get the threads end in an other order than they've been started
System.Threading.Thread.Sleep(rand.Next(500, 2000));
return source;
}));
}
static readonly String[] forums = new string[]
{
"announce",
"whatforum",
"reportabug",
"suggest",
"Offtopic",
"msdnsandbox",
"netfxsetup",
"netfxbcl",
"wpf",
"regexp",
"msbuild",
"netfxjscript",
"clr",
"netfxtoolsdev",
"asmxandxml",
"netfx64bit",
"netfxremoting",
"netfxnetcom",
"MEFramework",
"ncl",
"wcf",
"Geneva",
"MSWinWebChart",
"dublin",
"oslo",
// … some more elements
};
}
}
謝謝李。我顯然是這個行業的新人,到現在爲止我沒有使用UI。但我試圖一步一步來MVVM。你幫助我再接近一小步。這應該是足夠的今天,因爲它只是另外:) – germanSharper 2012-02-13 13:00:08