アクセス数 累計:000,126,008 昨日:000,000,080 本日:000,000,033
|
|
|
|
【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. |
|
|
|