「CriticalSectionクラス」の版間の差分
提供:AB開発Wiki
ナビゲーションに移動検索に移動
(Win32クリティカルセクションのラッパクラス) |
細 (#127) |
||
| 1行目: | 1行目: | ||
'''CriticalSection''' クラスは、Windowsのクリティカルセクションをラップするクラスです。 | '''CriticalSection'''クラスは、Windowsのクリティカルセクションをラップするクラスです。 | ||
クリティカルセクションは、スレッド間で同期を取るためのWin32オブジェクトの1つです。 | クリティカルセクションは、スレッド間で同期を取るためのWin32オブジェクトの1つです。 | ||
| 5行目: | 5行目: | ||
==クラスの機能== | ==クラスの機能== | ||
===継承するインタフェース=== | ===継承するインタフェース=== | ||
*[[ | *[[IDisposableインタフェース]] | ||
===メソッド=== | ===メソッド=== | ||
====コンストラクタ==== | ====コンストラクタ==== | ||
| 22行目: | 22行目: | ||
Function Enter() As CriticalSectionLock | Function Enter() As CriticalSectionLock | ||
;戻り値 | ;戻り値 | ||
:[[ | :[[CriticalSectionLockクラス]]のインスタンス | ||
このメソッドは、クリティカルセクションの所有権を得るまで待機します。 | このメソッドは、クリティカルセクションの所有権を得るまで待機します。 | ||
| 81行目: | 81行目: | ||
Sleep(-1) | Sleep(-1) | ||
</pre> | </pre> | ||
これを実行すると、例えば次のように出力されることがあります(常にこうなるとは限りません)。 | |||
abc | abc | ||
abc | abc | ||
| 162行目: | 162行目: | ||
de | de | ||
[[Category: | [[Category:ActiveBasic.Windows名前空間]] | ||
2007年8月5日 (日) 10:12時点における版
CriticalSectionクラスは、Windowsのクリティカルセクションをラップするクラスです。
クリティカルセクションは、スレッド間で同期を取るためのWin32オブジェクトの1つです。
クラスの機能
継承するインタフェース
メソッド
コンストラクタ
Sub CriticalSection()
デストラクタ
Sub ~CriticalSection()
Disposeを呼びます。
Dispose
クリティカルセクションオブジェクトを解放します。
Sub Dispose()
Enter
クリティカルセクションへ入ります。
Function Enter() As CriticalSectionLock
- 戻り値
- CriticalSectionLockクラスのインスタンス
このメソッドは、クリティカルセクションの所有権を得るまで待機します。
例
まずはクリティカルセクションを使用せず、データに異常を来たす例です。
#console
#require <Classes/System/Threading/Thread.ab>
'共有資源
Type StringData
str[16] As TCHAR
len As SIZE_T
End Type
Dim data As StringData
Function TestProc(args As VoidPtr) As Long
Do
Dim buf[16] As TCHAR
Dim i As Long
Dim s = Nothing As String
'異常を発生させやすくするため、わざと時間をかけて処理する
With data
For i = 0 To ELM(.len)
buf[i] = .str[i]
Sleep(60)
Next
s = New String(buf, .len As Long)
End With
Print s
Sleep(0)
Loop
End Function
Sub SetStringData(ByRef data As StringData)
'出力文字列の変更
With data
lstrcpy(.str, ToTCStr("de"))
.len = lstrlen(.str)
End With
End Sub
With data
lstrcpy(.str, ToTCStr("abc"))
.len = lstrlen(.str)
End With
Dim t As Thread(AddressOf(TestProc),0)
t.Start()
Sleep(1000)
SetStringData(data)
Sleep(-1)
これを実行すると、例えば次のように出力されることがあります(常にこうなるとは限りません)。
abc abc ae de de de
この場合では3行目の出力が異常なものになっています。これは、複数のスレッドが同時に変数strとlenを操作していることが原因です。
これをクリティカルセクションで保護すると次のようになります。
#console
#require <Classes/System/Threading/Thread.ab>
#require <Classes/ActiveBasic/Windows/CriticalSection.ab>
'共有資源
Type StringData
str[16] As TCHAR
len As SIZE_T
End Type
Dim data As StringData
Dim cs = New ActiveBasic.Windows.CriticalSection
Function TestProc(args As VoidPtr) As Long
Do
Dim buf[16] As TCHAR
Dim i As Long
Dim s = Nothing As String
Dim lock = cs.Enter
With data
For i = 0 To ELM(.len)
buf[i] = .str[i]
Sleep(60)
Next
s = New String(buf, .len As Long)
End With
lock.Leave()
Print s
Sleep(0)
Loop
End Function
Sub SetStringData(ByRef data As StringData)
Dim lock = cs.Enter
With data
lstrcpy(.str, ToTCStr("de"))
.len = lstrlen(.str)
End With
lock.Leave()
End Sub
With data
lstrcpy(.str, ToTCStr("abc"))
.len = lstrlen(.str)
End With
Dim t As Thread(AddressOf(TestProc),0)
t.Start()
Sleep(1000)
SetStringData(data)
Sleep(-1)
今度は行単位でデータの整合性が取れた出力になっています。
abc abc abc de de de de de de