Windows Formsの「同時編集」という悪夢を終わらせる:排他制御の極意
こんにちは。現場で泥臭いトラブルをいくつも乗り越えてきたエンジニアです。
Windows Formsで業務アプリを作っていると、必ずぶち当たる壁があります。それが「複数人で同じデータを触ったとき、後勝ちでデータが上書きされる」という悲劇です。
Excelのマクロから脱却し、本格的な業務アプリを作るなら、「誰が今このデータを触っているか」を管理する排他制御は避けて通れません。今回は、現場で必ず使う「楽観的排他」と「アプリ間排他」の考え方を伝授します。
—
1. データベースの「楽観的排他制御」とは?
「楽観的排他」とは、一言で言えば「編集する瞬間までロックは掛けないが、更新する瞬間に他人が触っていないか確認する」という手法です。
なぜ「楽観」なのか?
もし編集画面を開いた瞬間にDBをロックすると、誰かが画面を開いたまま席を外したら、他の人は誰も作業ができなくなりますよね。これでは業務が止まります。
そこで、「最後に読み込んだ値と、今DBにある値が同じならOK」というルールを作るのです。
実装の鍵:バージョンカラム
DBテーブルに `Version` という数値カラムを追加します。
1. データ取得: `SELECT FROM Orders WHERE ID = 1` (この時 `Version=5` とする)
2. 編集: ユーザーが画面で値を書き換える。
3. 更新: `UPDATE Orders SET Value=’A’, Version=6 WHERE ID=1 AND Version=5`
【ここがポイント!】
もし、あなたが編集している間に別の誰かが更新を完了していれば、DBのVersionは「6」になっています。すると、上記のSQLの `WHERE Version=5` に一致する行が見つからず、更新件数が0件になります。この瞬間に「データが競合しました」と例外を投げればいいのです。
—
2. ローカルファイルを守る:Mutex(ミューテックス)
次に、設定ファイルやローカルのAccessファイルなどを扱う際に「アプリを二重起動させたくない」「別のプロセスからファイルを触られたくない」というケースです。ここで登場するのが `Mutex` です。
Mutexは「通行手形」のようなもの。これを持っているプロセスしか、特定の処理はできません。
Mutexを使った二重起動防止(VB.NET)
Imports System.Threading
Public Class Form1
‘ アプリ全体でユニークな名前を付ける
Private Shared mutex As Mutex = New Mutex(False, “MyApplication_Unique_Name_2023”)
Shared Sub Main()
‘ 手形が取れなければ既に起動中と判断
If Not mutex.WaitOne(0, False) Then
MessageBox.Show(“既に起動しています。”)
Return
End If
Try
Application.Run(New Form1())
Finally
‘ 終了時に解放する
mutex.ReleaseMutex()
End Try
End Sub
End Class
—
3. ファイル操作の鉄則:FileStreamの共有モード
ローカルファイルを読み書きする際、単純な `IO.File.ReadAllText` だと、他のプロセスが書き込み中だった場合にエラーになります。これを防ぐには `FileStream` で共有モードを明示します。
Imports System.IO
Public Sub SafeWriteToFile(filePath As String, content As String)
‘ FileShare.None を指定することで、他のプロセスからのアクセスを完全に拒否する
Using fs As New FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)
Using sw As New StreamWriter(fs)
sw.Write(content)
End Using
End Using
Catch ex As IOException
‘ ここで「現在ファイルが使用中です」とユーザーに通知する
MessageBox.Show(“現在ファイルが使用中です。しばらくしてから再試行してください。”)
End Sub
—
現場エンジニアからのメッセージ
初心者が陥りやすい最大の罠は、「エラーを無視する」ことです。
「排他制御を実装するとコードが複雑になるから…」と逃げると、必ず「データが消えた!」「整合性が取れない!」という修羅場が訪れます。
- DBデータ: `Version` カラムによる楽観的排他。
- アプリ二重起動: `Mutex` でガード。
- ローカルファイル: `FileShare` モードを意識したストリーム操作。
この3つを組み合わせるだけで、あなたのアプリの信頼性は格段に向上します。「なんとなく動く」から「堅牢に動く」へ。ここをクリアすれば、あなたはもう立派な業務自動化エンジニアの入り口に立っていますよ。
何か一つでも詰まったら、遠慮なくまた聞いてくださいね。応援しています!
