在Silverlight中,使用Thread,Timer,BackgrouWorker,ThreadPool可以实现多线程开发。但是随之而来的问题是如何跨线程访问资源呢?下面先以Timer计时器为例讲解:
示例
1、Timer.xaml
1 <UserControl x:Class="ThreadDemo.Timer"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6 mc:Ignorable="d"
7 d:DesignHeight="300" d:DesignWidth="400">
8
9 <Grid x:Name="LayoutRoot" Background="White">
10 <ScrollViewer>
11 <StackPanel x:Name="timerNum">
12
13 </StackPanel>
14 </ScrollViewer>
15 </Grid>
16 </UserControl>
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6 mc:Ignorable="d"
7 d:DesignHeight="300" d:DesignWidth="400">
8
9 <Grid x:Name="LayoutRoot" Background="White">
10 <ScrollViewer>
11 <StackPanel x:Name="timerNum">
12
13 </StackPanel>
14 </ScrollViewer>
15 </Grid>
16 </UserControl>
Timer.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Net;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Documents;
8 using System.Windows.Input;
9 using System.Windows.Media;
10 using System.Windows.Media.Animation;
11 using System.Windows.Shapes;
12 using System.Threading;
13
14 namespace ThreadDemo
15 {
16 public partial class Timer: UserControl
17 {
18 public Timer()
19 {
20 InitializeComponent();
21 ///实例化一个Timer时间器
22 System.Threading.TimerTimer timer = new System.Threading.TimerTimer(new TimerCallback(TimerProc));
23 ///设定500毫秒后启动,每隔1000毫秒执行一次
24 timer.Change(500, 1000);
25 }
26 int flagnum;
27 public void TimerProc(object state)
28 {
29 flagnum++;
30 TextBlock _temptext = new TextBlock();
31 _temptext.Text = flagnum.ToString();
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Net;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Documents;
8 using System.Windows.Input;
9 using System.Windows.Media;
10 using System.Windows.Media.Animation;
11 using System.Windows.Shapes;
12 using System.Threading;
13
14 namespace ThreadDemo
15 {
16 public partial class Timer: UserControl
17 {
18 public Timer()
19 {
20 InitializeComponent();
21 ///实例化一个Timer时间器
22 System.Threading.TimerTimer timer = new System.Threading.TimerTimer(new TimerCallback(TimerProc));
23 ///设定500毫秒后启动,每隔1000毫秒执行一次
24 timer.Change(500, 1000);
25 }
26 int flagnum;
27 public void TimerProc(object state)
28 {
29 flagnum++;
30 TextBlock _temptext = new TextBlock();
31 _temptext.Text = flagnum.ToString();
32 timerNum.Children.Add(_temptext);
33
34 }
35 }
36 }
F5运行程序,Visual Studio报错,跨线程访问无效。
这里使用TimerCallback委托指定希望Timer执行的方法,但是此方法不能在计时器线程上执行,所以这里就存在一个跨线程访问的问题。下面调整下代码,计时器线程将该工作委托给与该UI线程关联的Dispatcher。使用Dispatcher.BeginInvoke.
2、Timer.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Net;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Documents;
8 using System.Windows.Input;
9 using System.Windows.Media;
10 using System.Windows.Media.Animation;
11 using System.Windows.Shapes;
12 using System.Threading;
13
14 namespace ThreadDemo
15 {
16 public partial class Timer: UserControl
17 {
18 public Timer()
19 {
20 InitializeComponent();
21 ///实例化一个Timer时间器
22 System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(TimerProc));
23 ///设定500毫秒后启动,每隔1000毫秒执行一次
24 timer.Change(500, 1000);
25 }
26 int flagnum;
27 public void TimerProc(object state)
28 {
29 ///在计时器的线程上使用Dispather.BeginInvoke,将计时器线程上的工作委托给UI线程关联的Dispatcher
30 this.Dispatcher.BeginInvoke(delegate
31 {
32 flagnum++;
33 TextBlock _temptext = new TextBlock();
34 _temptext.Text = flagnum.ToString();
35 timerNum.Children.Add(_temptext);
36 });
37
38
39 }
40 } 41 }
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Net;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Documents;
8 using System.Windows.Input;
9 using System.Windows.Media;
10 using System.Windows.Media.Animation;
11 using System.Windows.Shapes;
12 using System.Threading;
13
14 namespace ThreadDemo
15 {
16 public partial class Timer: UserControl
17 {
18 public Timer()
19 {
20 InitializeComponent();
21 ///实例化一个Timer时间器
22 System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(TimerProc));
23 ///设定500毫秒后启动,每隔1000毫秒执行一次
24 timer.Change(500, 1000);
25 }
26 int flagnum;
27 public void TimerProc(object state)
28 {
29 ///在计时器的线程上使用Dispather.BeginInvoke,将计时器线程上的工作委托给UI线程关联的Dispatcher
30 this.Dispatcher.BeginInvoke(delegate
31 {
32 flagnum++;
33 TextBlock _temptext = new TextBlock();
34 _temptext.Text = flagnum.ToString();
35 timerNum.Children.Add(_temptext);
36 });
37
38
39 }
40 } 41 }
F5运行成功
接下来,我们再用AsyncOperation来实现跨线程访问。
3、Thread.xaml
1 <UserControl x:Class="ThreadDemo.Thread"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6 mc:Ignorable="d"
7 d:DesignHeight="300" d:DesignWidth="400">
8
9 <Grid x:Name="LayoutRoot" Background="White">
10 <ScrollViewer>
11 <StackPanel x:Name="timerNum">
12
13 </StackPanel>
14 </ScrollViewer>
15 </Grid>16 </UserControl>
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6 mc:Ignorable="d"
7 d:DesignHeight="300" d:DesignWidth="400">
8
9 <Grid x:Name="LayoutRoot" Background="White">
10 <ScrollViewer>
11 <StackPanel x:Name="timerNum">
12
13 </StackPanel>
14 </ScrollViewer>
15 </Grid>16 </UserControl>
Thread.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Net;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Documents;
8 using System.Windows.Input;
9 using System.Windows.Media;
10 using System.Windows.Media.Animation;
11 using System.Windows.Shapes;
12 using System.ComponentModel;
13
14 namespace ThreadDemo
15 {
16 public partial class Thread : UserControl
17 {
18 private AsyncOperation async;
19
20 public Thread()
21 {
22 InitializeComponent();
23 async = AsyncOperationManager.CreateOperation(null);
24 System.Threading.Thread thread = new System.Threading.Thread(TimerProc);
25 thread.Start();
26 }
27
28 public void TimerProc()
29 {
30
31 async.Post(delegate
32 {
33
34 TextBlock _temptext = new TextBlock();
35 _temptext.Text ="0";
36 timerNum.Children.Add(_temptext);
37
38 }, null);
39
40 }
41
42
43 }44 }
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Net;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Documents;
8 using System.Windows.Input;
9 using System.Windows.Media;
10 using System.Windows.Media.Animation;
11 using System.Windows.Shapes;
12 using System.ComponentModel;
13
14 namespace ThreadDemo
15 {
16 public partial class Thread : UserControl
17 {
18 private AsyncOperation async;
19
20 public Thread()
21 {
22 InitializeComponent();
23 async = AsyncOperationManager.CreateOperation(null);
24 System.Threading.Thread thread = new System.Threading.Thread(TimerProc);
25 thread.Start();
26 }
27
28 public void TimerProc()
29 {
30
31 async.Post(delegate
32 {
33
34 TextBlock _temptext = new TextBlock();
35 _temptext.Text ="0";
36 timerNum.Children.Add(_temptext);
37
38 }, null);
39
40 }
41
42
43 }44 }
ok.源码下载