マルチスレッドプログラミング(C++編)に続き、今度はVB.net編を公開。マルチスレッドプログラミング(C#編)はこちら。
Visual Studio 2010 VB.netのプロジェクト一式はこちら。

Cしか書けないアラフィフのおいらがVBをいきなり書けるようになるわけないので、以下のコードは人に書いてもらったもの。おいらがやったことといえば、ちょちょいとUIの説明文を変えただけ。C#に書き換えるくらいのことはやろうと一瞬思ったんだけど、いかんせんモチベーションがあがらずVBのまま公開することとした。
マルチスレッドゆえの注意事項も案内してもらったので、以下に記載。
其の一、スレッド実行中はメインスレッドと共有する値を変更してはいけない。どうしても変更したいなら各種同期オブジェクトを使用すべし。ManualResetEventは同期オブジェクトなのでよいし、32bit以下のデータ(Boolean、Integerなど)は書き込んでもOK。canceledはBooleanなのでOK。
其の二、スレッド内から直接コントロールを触ってはいけない。どうしても触りたい場合は、デリゲートを作成した上でMe.Invoke()経由で実行する。
以下、ソースコードを転記。
Imports System.Threading
Public Class Form1
Private canceled As Boolean = False
Private count As Integer = 0
Private workerThread As Thread
Private mre As ManualResetEvent = New ManualResetEvent(True)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Button1.Enabled = False
Button2.Enabled = True
canceled = False
ClearCount()
workerThread = New Thread(New ThreadStart(AddressOf Work))
workerThread.IsBackground = True
workerThread.Start()
End Sub
Private Sub Work()
Try
Dim i As Integer
For i = 1 To 10
Me.Invoke(Sub() IncrementCount())
Thread.Sleep(3000) 'この処理を実際の時間がかかる処理に置き換える
mre.WaitOne()
If canceled Then
Me.Invoke(Sub() ThreadCompleted(1))
Exit Sub
End If
Next
Me.Invoke(Sub() ThreadCompleted(0))
Catch ex As Exception
Me.Invoke(Sub() ThreadCompleted(2))
End Try
End Sub
Private Sub ThreadCompleted(ByVal state As Integer)
If state = 0 Then
MessageBox.Show("正常終了", "情報", MessageBoxButtons.OK, MessageBoxIcon.Information)
ElseIf state = 1 Then
ClearCount()
MessageBox.Show("中断", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
ClearCount()
MessageBox.Show("異常終了", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
Button1.Enabled = True
Button2.Enabled = False
canceled = False
workerThread = Nothing
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
mre.Reset()
Try
If MessageBox.Show("中止しますか?", "質問", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
canceled = True
Button2.Enabled = False
End If
Finally
mre.Set()
End Try
End Sub
Private Sub Form1_FormClosing(ByVal sender As System.Object,
ByVal e As System.Windows.Forms.FormClosingEventArgs) _
Handles MyBase.FormClosing
If workerThread IsNot Nothing Then e.Cancel = True
End Sub
Private Sub ClearCount()
count = 0
UpdateText()
End Sub
Private Sub IncrementCount()
count = count + 1
UpdateText()
End Sub
Private Sub UpdateText()
Label1.Text = String.Format("時間のかかる処理を実行中。{0}/10", count)
End Sub
End Class
以下の記事を読むと、マルチスレッド処理(非同期処理)についての歴史や最新技術がよくわかると案内されている。ふむふむ、おいらでもよくわかるように解説されているなぁ。やっぱasync/awaitか。。
.NET開発における非同期処理の基礎と歴史