[源碼下載]
作者:webabcd
介紹
Silverlight 2.0 使用Lock, Interlocked, EventWaitHandle, Monitor來實現線程同步
Lock - 確保代碼塊完成運行,而不會被其他線程中斷
Interlocked - 爲多個線程共享的變量提供原子級的操作
EventWaitHandle - 通知其他線程是否可入的類
Monitor - 提供同步訪問對象的機制
ThreadStaticAttribute - 所指定的靜態變量對每個線程都是唯一的
在線DEMO
http://www.cnblogs.com/webabcd/archive/2008/10/09/1307486.html
示例
1、Lock.xaml
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel HorizontalAlignment="Left" Margin="5">
<TextBlock x:Name="txtMsg" />
</StackPanel>
</UserControl>
Lock.xaml.cs
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;
namespace Silverlight20.Thread
{
public partial class Lock : UserControl
{
// 需要被 lock 的靜態變量
private static readonly object objLock = new object();
private static int i;
public Lock()
{
InitializeComponent();
i = 0;
for (int x = 0; x < 100; x++)
{
// 開 100 個線程去操作靜態變量 i
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(DoWork));
thread.Start();
}
System.Threading.Thread.Sleep(3000);
// 3 秒後 100 個線程都應該執行完畢了,取得 i 的結果
// 做了併發處理的結果爲 100 ,去掉 lock 可得到不做併發處理的結果
txtMsg.Text = i.ToString();
}
private void DoWork()
{
try
{
// lock() - 確保代碼塊完成運行,而不會被其他線程中斷。其參數必須爲一個引用類型的對象
lock (objLock)
{
int j = i + 1;
// 模擬多線程併發操作靜態變量 i 的情況
System.Threading.Thread.Sleep(10);
i = j;
}
}
finally
{
// code
}
}
}
}
2、Interlocked.xaml
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel HorizontalAlignment="Left" Margin="5">
<TextBlock x:Name="txtMsg" />
</StackPanel>
</UserControl>
Interlocked.xaml.cs
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;
namespace Silverlight20.Thread
{
public partial class Interlocked : UserControl
{
private static int i;
public Interlocked()
{
InitializeComponent();
i = 0;
for (int x = 0; x < 100; x++)
{
// 開 100 個線程去操作靜態變量 i
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(DoWork));
thread.Start();
}
System.Threading.Thread.Sleep(1000);
// 1 秒後 100 個線程都應該執行完畢了,取得 i 的結果
txtMsg.Text = i.ToString();
}
private void DoWork()
{
try
{
// Interlocked - 爲多個線程共享的變量提供原子級的操作(避免併發問題)
// i 加 1
System.Threading.Interlocked.Increment(ref i);
// i 減 1
System.Threading.Interlocked.Decrement(ref i);
// i 加 1
System.Threading.Interlocked.Add(ref i, 1);
// 如果 i 等於 100 ,則將 i 賦值爲 101
System.Threading.Interlocked.CompareExchange(ref i, 101, 100);
// 將 i 賦值爲 1000
// System.Threading.Interlocked.Exchange(ref i, 1000);
}
finally
{
// code
}
}
}
}
3、EventWaitHandle.xaml
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel HorizontalAlignment="Left" Margin="5">
<TextBlock x:Name="txtAutoResetEvent" />
<TextBlock x:Name="txtManualResetEvent" />
</StackPanel>
</UserControl>
EventWaitHandle.xaml.cs
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;
namespace Silverlight20.Thread
{
public partial class EventWaitHandle : UserControl
{
// AutoResetEvent(bool state) - 通知其他線程是否可入的類,自動 Reset()
// bool state - 是否爲終止狀態,即是否禁止其他線程入內
private System.Threading.AutoResetEvent autoResetEvent =
new System.Threading.AutoResetEvent(false);
// ManualResetEvent(bool state) - 通知其他線程是否可入的類,手動 Reset()
// bool state - 是否爲終止狀態,即是否禁止其他線程入內
private System.Threading.ManualResetEvent manualResetEvent =
new System.Threading.ManualResetEvent(false);
private static int i;
public EventWaitHandle()
{
InitializeComponent();
// 演示 AutoResetEvent
AutoResetEventDemo();
// 演示 ManualResetEvent
ManualResetEventDemo();
}
private void AutoResetEventDemo()
{
i = 0;
for (int x = 0; x < 100; x++)
{
// 開 100 個線程去操作靜態變量 i
System.Threading.Thread thread =
new System.Threading.Thread(new System.Threading.ThreadStart(AutoResetEventDemoCallback));
thread.Start();
// 阻塞當前線程,直到 AutoResetEvent 發出 Set() 信號
autoResetEvent.WaitOne();
}
System.Threading.Thread.Sleep(1000);
// 1 秒後 100 個線程都應該執行完畢了,取得 i 的結果
txtAutoResetEvent.Text = i.ToString();
}
private void AutoResetEventDemoCallback()
{
try
{
int j = i + 1;
// 模擬多線程併發操作靜態變量 i 的情況
System.Threading.Thread.Sleep(5);
i = j;
}
finally
{
// 發出 Set() 信號,以釋放 AutoResetEvent 所阻塞的線程
autoResetEvent.Set();
}
}
private void ManualResetEventDemo()
{
i = 0;
for (int x = 0; x < 100; x++)
{
// Reset() - 將 ManualResetEvent 變爲非終止狀態,即由此線程控制 ManualResetEvent,
// 其他線程排隊,直到 ManualResetEvent 發出 Set() 信號(AutoResetEvent 在 Set() 時會自動 Reset())
manualResetEvent.Reset();
// 開 100 個線程去操作靜態變量 i
System.Threading.Thread thread =
new System.Threading.Thread(new System.Threading.ThreadStart(ManualResetEventDemoCallback));
thread.Start();
// 阻塞當前線程,直到 ManualResetEvent 發出 Set() 信號
manualResetEvent.WaitOne();
}
System.Threading.Thread.Sleep(1000);
// 1 秒後 100 個線程都應該執行完畢了,取得 i 的結果
txtManualResetEvent.Text = i.ToString();
}
private void ManualResetEventDemoCallback()
{
try
{
int j = i + 1;
// 模擬多線程併發操作靜態變量 i 的情況
System.Threading.Thread.Sleep(5);
i = j;
}
finally
{
// 發出 Set() 信號,以釋放 ManualResetEvent 所阻塞的線程,同時 ManualResetEvent 變爲終止狀態)
manualResetEvent.Set();
}
}
}
}
4、Monitor.xaml
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel HorizontalAlignment="Left" Margin="5">
<TextBlock x:Name="txtMsg" />
</StackPanel>
</UserControl>
Monitor.xaml.cs
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;
namespace Silverlight20.Thread
{
public partial class Monitor : UserControl
{
private static readonly object objLock = new object();
private static int i;
public Monitor()
{
InitializeComponent();
i = 0;
for (int x = 0; x < 100; x++)
{
// 開 100 個線程去操作靜態變量 i
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(DoWork));
thread.Start();
}
System.Threading.Thread.Sleep(1000);
// 1 秒後 100 個線程都應該執行完畢了,取得 i 的結果
txtMsg.Text = i.ToString();
}
private void DoWork()
{
try
{
// Monitor - 提供同步訪問對象的機制
// Enter() - 在指定對象上獲取排他鎖
System.Threading.Monitor.Enter(objLock);
int j = i + 1;
// 模擬多線程併發操作靜態變量 i 的情況
System.Threading.Thread.Sleep(5);
i = j;
// Exit() - 釋放指定對象上的排他鎖
System.Threading.Monitor.Exit(objLock);
}
finally
{
// code
}
}
}
}
5、ThreadStaticAttribute.xaml
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel HorizontalAlignment="Left" Margin="5">
<TextBlock x:Name="txtMsg" />
<TextBlock x:Name="txtMsg2" />
</StackPanel>
</UserControl>
ThreadStaticAttribute.xaml.cs
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;
namespace Silverlight20.Thread
{
public partial class ThreadStaticAttribute : UserControl
{
// ThreadStatic - 所指定的靜態變量對每個線程都是唯一的
[System.ThreadStatic]
private static int value;
// 一般的靜態變量,對每個線程都是共用的
private static int value2;
public ThreadStaticAttribute()
{
InitializeComponent();
Demo();
}
void Demo()
{
System.Threading.Thread thread = new System.Threading.Thread(DoWork);
thread.Name = "線程1";
thread.Start();
System.Threading.Thread.Sleep(100);
System.Threading.Thread thread2 = new System.Threading.Thread(DoWork2);
thread2.Name = "線程2";
thread2.Start();
}
void DoWork()
{
for (int i = 0; i < 10; i++)
{
// 線程1對靜態變量的操作
value++;
value2++;
}
string s = value.ToString(); // value - 本線程獨有的靜態變量
string s2 = value2.ToString(); // value2 - 所有線程共用的靜態變量
this.Dispatcher.BeginInvoke(delegate { txtMsg.Text = s + " - " + s2; });
// this.Dispatcher.BeginInvoke(delegate { txtMsg.Text = value + " - " + value2; }); // 在UI線程上調用,所以value值爲UI線程上的value值,即 0
}
void DoWork2()
{
for (int i = 0; i < 10; i++)
{
// 線程2對靜態變量的操作
value++;
value2++;
}
string s = value.ToString(); // value - 本線程獨有的靜態變量
string s2 = value2.ToString(); // value2 - 所有線程共用的靜態變量
this.Dispatcher.BeginInvoke(delegate { txtMsg2.Text = s + " - " + s2; });
// this.Dispatcher.BeginInvoke(delegate { txtMsg2.Text = value + " - " + value2; }); // 在UI線程上調用,所以value值爲UI線程上的value值,即 0
}
}
}
OK
[源碼下載]