すらすらプログラマーへのお問い合わせ
すらすらのブログ
アクセス数  累計:000,683,168  昨日:000,000,189  本日:000,000,006
Loading
スレッド
.NET プログラミング
プロパティグリッド
印刷
リストボックス
スレッド
リストビュー
インストーラー
やってみよう!

できるVisual Studio 2015 Windows /Android/iOS アプリ対応

独習C# 第3版

VisualBasic2013パーフェクトマスター (Perfect Master SERIES)

プログラミング.NET Framework 第4版 (Microsoft Press)

VisualBasic2013逆引き大全555の極意

猫でもわかるWindowsプログラミング 第4版 (猫でもわかるプログラミング)

VisualC#2013逆引き大全555の極意

スレッドロック② 最終更新:2010/07/15
【Amazon ランキング:本 - コンピュータ・IT】

前回は SyncLock キーワードを使ってスレッド間で排他ロックを行いましたが、SyncLock では値を変更しない場合でも処理がロックされてしまい効率が悪い場合があります。
そのような場合のために ReaderWriterLock クラス用意されています。ReaderWriterLock クラスは ReaderLock、WriterLock の2つのロックモードを持っています。 WriterLock を行った場合は他のスレッドからは ReaderLock も WriterLock も行うことはできない排他ロック状態になりますが、 ReaderLock の場合は他のスレッドから WriterLock はできませんが ReaderLock は行う事ができます。
なので、参照しか行わない場合は ReaderLock をかけることにより他のスレッドがロックを開放するのを待たなくて済むようになります。


読み込みロック
読み込みロックを行うには AcquireReaderLock() メソッドと ReleaseReaderLock() を使用します。AcquireReaderLock() メソッドにはタイムアウト時間をミリ秒で指定できます。タイムアウトせずに待ち続ける場合は Timeout.Infinite を指定します。
ReaderLock をかけて指定した時間ロックが解除されなかった場合は ApplicationException がスローされます。
[VB]
' 1秒でタイムアウト
_rwLock.AcquireReaderLock(1000)
' タイムアウトしない
_rwLock.AcquireReaderLock(Timeout.Infinite)
' ロック解除
_rwLock.ReleaseReaderLock()

[C#]
// 1秒でタイムアウト
_rwLock.AcquireReaderLock(1000);
// タイムアウトしない
_rwLock.AcquireReaderLock(Timeout.Infinite);
// ロック解除
_rwLock.ReleaseReaderLock();
書き込みロック
書き込みロックを行うには AcquireWriterLock() メソッドと ReleaseWriterLock() を使用します。AcquireWriterLock() メソッドにはタイムアウト時間をミリ秒で指定できます。タイムアウトせずに待ち続ける場合は Timeout.Infinite を指定します。
WriterLock をかけて指定した時間ロックが解除されなかった場合は ApplicationException がスローされます。
[VB]
' 1秒でタイムアウト
_rwLock.AcquireWriterLock(1000)
' タイムアウトしない
_rwLock.AcquireWriteLock(Timeout.Infinite)
' ロック解除
_rwLock.ReleaseWriteLock()

[C#]
// 1秒でタイムアウト
_rwLock.AcquireWriteLock(1000);
// タイムアウトしない
_rwLock.AcquireWriteLock(Timeout.Infinite);
// ロック解除
_rwLock.ReleaseWriteLock();
フォームの作成
Form1 に Button, ProgressBar,Timer をはりつけます。
プロパティの内容はすべてデフォルトです。

Button:[Button1]
ProgressBar:[ProgressBar1]
Timer:[Timer1]

VB[Form1.vb]
Imports System.Threading

Public Class Form1

    
Private _progressValue As Integer = 0
    
Private _thread As Thread = Nothing
    Private _rwLock As ReaderWriterLock = New ReaderWriterLock()

    
Public Sub New()

        
' この呼び出しは、Windows フォーム デザイナで必要です。
        InitializeComponent()

        
' プログレスバー更新タイマー開始
        timer1.Interval = 200
        timer1.Enabled = 
True

    End Sub

    Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        
Handles button1.Click


        
If Not _thread Is Nothing Then

            Console.WriteLine(_thread.ThreadState.ToString())

            
' スレッドが停止状態でない場合は終了
            If _thread.ThreadState <> ThreadState.Stopped Then
                Exit Sub
            End If
        End If

        ' スレッド開始
        _thread = New Thread(AddressOf ThreadProc)
        _thread.Start()

    
End Sub

    ' スレッド処理
    Private Sub ThreadProc()

        
For i As Integer = 0 To 10

            
' 値を更新する間書き込みロックする
            ' Timeout.Infinite を指定するとタイムアウトなし
            _rwLock.AcquireWriterLock(Timeout.Infinite)

            
'プログレスの値加算
            _progressValue = i * 10

            
' ロック解除
            _rwLock.ReleaseWriterLock()

            Thread.Sleep(1000)
        
Next

    End Sub

    Private Sub timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        
Handles timer1.Tick

        
Try
            ' プログレスバーを更新する間読み込みロックする
            ' タイムアウト時間 0.5秒 を経過すると ApplicationException が発生
            _rwLock.AcquireReaderLock(500)

            
' プログレスバー更新
            Me.progressBar1.Value = _progressValue

            
' ロック解除
            _rwLock.ReleaseReaderLock()

        
Catch ex As ApplicationException
            
' タイマー停止
            Me.timer1.Enabled = False

            ' エラーメッセージ表示
            MessageBox.Show(ex.ToString())

        
Finally
            ' ロック中の場合解除
            If _rwLock.IsReaderLockHeld Then
                _rwLock.ReleaseReaderLock()
            
End If
        End Try
    End Sub
End
 Class
C#[Form1.cs]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ThreadCS
{
    
public partial class Form1 : Form
    {
        
private int _progressValue = 0;
        
private Thread _thread = null;
        
private ReaderWriterLock _rwLock = new ReaderWriterLock();

        
public Form1()
        {
            InitializeComponent();

            
// プログレス更新タイマー開始
            timer1.Interval = 200;
            timer1.Enabled = 
true;
        }

        
private void button1_Click(object sender, EventArgs e)
        {
            
if (_thread != null)
            {
                
Console.WriteLine(_thread.ThreadState.ToString());

                
// スレッドが停止状態でない場合は終了
                if (_thread.ThreadState != ThreadState.Stopped)
                    
return;
            }

            
// スレッド開始
            _thread = new Thread(ThreadProc);
            _thread.Start();
        }

        
// スレッド処理
        private void ThreadProc()
        {
            
for (int i = 0; i <= 10; i++)
            {
                
// 値を更新する間書き込みロックする
                // Timeout.Infinite を指定するとタイムアウトなし
                _rwLock.AcquireWriterLock(Timeout.Infinite);

                
// プログレスの値加算
                _progressValue = i * 10;

                
// ロック解除
                _rwLock.ReleaseWriterLock();

                
Thread.Sleep(1000);
            }
        }

        
// プログレスバーを更新するタイマー
        private void timer1_Tick(object sender, EventArgs e)
        {
            
try
            {
                
// プログレスバーを更新する間読み込みロックする
                // タイムアウト時間 0.5秒 を経過すると ApplicationException が発生
                _rwLock.AcquireReaderLock(500);

                
// プログレスバー更新
                this.progressBar1.Value = _progressValue;

            }
            
catch (ApplicationException ex)
            {
                
// タイマー停止
                this.timer1.Enabled = false;

                
// エラーメッセージ表示
                MessageBox.Show(ex.ToString());
            }
            
finally
            {
                
// ロック中の場合解除
                if (_rwLock.IsReaderLockHeld)
                    _rwLock.ReleaseReaderLock();
            }
        }
    }
}
タイムアウトエラー
上記のサンプルの timer1_Tick イベントでタイムアウトエラーをキャッチするようにしていますが、このままではまずエラーは発生しないです。 ThreadProc() の内容を次のように修正してください。するとタイムアウトエラーが発生すると思います。
[VB]
Private Sub ThreadProc()
    
For i As Integer = 0 To 10
        
' 値を更新する間書き込みロックする
        ' Timeout.Infinite を指定するとタイムアウトなし
        _rwLock.AcquireWriterLock(Timeout.Infinite)
        
'プログレスの値加算
        _progressValue = i * 10
        Thread.Sleep(1000)
        
' ロック解除
        _rwLock.ReleaseWriterLock()
    
Next
End
 Sub

[C#]
// スレッド処理
private void ThreadProc()
{
    
for (int i = 0; i <= 10; i++)
    {
        
// 値を更新する間書き込みロックする
        // Timeout.Infinite を指定するとタイムアウトなし
        _rwLock.AcquireWriterLock(Timeout.Infinite);
        
// プログレスの値加算
        _progressValue = i * 10;
        
Thread.Sleep(1000);
        
// ロック解除
        _rwLock.ReleaseWriterLock();
    }
}
※このページで紹介しているサンプルコードについて管理者は動作保障をいたしません※
※サンプルコードを使用する場合は、自己責任でお願いします※

【楽天 ランキング:パソコン・周辺機器 - ノートパソコン】




このサイトはフリーソフトのMerge HTMLで作成されています。
このサイトはリンクフリーです。

ページの先頭に戻る Copyright© 2010-2015 Jun.Shiozaki All rights reserved.