穩紮穩打Silverlight(26) - 2.0線程之Lock, Interlocked, EventWaitHandle, Monitor, ThreadStaticAttribute

 [索引頁]
[源碼下載]


穩紮穩打Silverlight(26) - 2.0線程之Lock, Interlocked, EventWaitHandle, Monitor, ThreadStaticAttribute


作者: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
<UserControl x:Class="Silverlight20.Thread.Lock"
    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;
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
<UserControl x:Class="Silverlight20.Thread.Interlocked"
    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;
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, 101100); 

                
// 將 i 賦值爲 1000
                
// System.Threading.Interlocked.Exchange(ref i, 1000);
            }

            
finally
            
{
                
// code
            }

        }

    }

}



3、EventWaitHandle.xaml
<UserControl x:Class="Silverlight20.Thread.EventWaitHandle"
    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;
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
<UserControl x:Class="Silverlight20.Thread.Monitor"
    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;
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
<UserControl x:Class="Silverlight20.Thread.ThreadStaticAttribute"
    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;
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
[源碼下載]
發佈了6 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章