tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルマルチスレッドについて
記事No6249
投稿日: 2007/09/07(Fri) 12:45
投稿者
Kと申します。
WindowsXP Pro+SP2 VB.net2003でマルチスレッドの勉強をしています。
VB.netは始めてから2ヶ月程度です。

かなりの処理時間のかかる処理をマルチスレッドで行っているのですが
スレッドが途中で止まってしまします。
早い時は3分程度、遅い時は40分程度で止まってしまします。
止まった時は、特にエラーは出ていません。
現在、再度確認を行っている所ですが、一度ソース内のコメント「'ここで止まってた」で
止まっていました。
デバッガでデバッグを行いましたが、スレッド部分はデバッグができない?
もし、スレッド部分もデバッグできるのであれば、アドバイスをいただけると助かります。
他に必要な情報があれば、言っていただければできる範囲で出しますので、コメントをお願いします。

以下に現在のソースの要約したものを載せますので、よきアドバイスをお願いいたします。

Public Class Form1
    Inherits System.Windows.Forms.Form

    Private Delegate Sub sampleCallDelegate()
    Private workerThread As Thread
    Public Start_Time As Date

    Private Sub TextBox_Disp()
        Me.TextBox1.Refresh()
        Me.TextBox2.Refresh()
        Me.TextBox3.Refresh()
    End Sub

    Private Sub Sub_A()
        Dim n, i, c As Long

        For n = 9223372036854775807 To 2 Step -1
            TextBox1.Text = n.ToString
            For i = 2 To (n / 2) + 1
                TextBox2.Text = i.ToString
                c = n Mod i
                If c = 0 Then
                    Exit For
                End If
        'ここで止まっていた。
                TextBox3.Text = c.ToString
                Me.Invoke(New sampleCallDelegate(AddressOf TextBox_Disp))
            Next
            If c <> 0 Then
                TextBox1.Text = n.ToString
                Exit For
            End If
        Next
    End Sub

    Private Sub START_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles START.Click

        workerThread = New System.Threading.Thread( _
                            New System.Threading.ThreadStart(AddressOf Sub_A))

        workerThread.IsBackground = True
        workerThread.Start()

    End Sub

End Class

[ツリー表示へ]
タイトルRe: マルチスレッドについて
記事No6253
投稿日: 2007/09/07(Fri) 14:39
投稿者魔界の仮面弁士
> 'ここで止まっていた。
> TextBox3.Text = c.ToString

TextBox3 のコントロールを、ワーカースレッドから操作することはできません。
(VB2005 なら、即座に不正処理の例外が発生するので分かりやすいのですけれどね)

[ツリー表示へ]
タイトルRe^2: マルチスレッドについて
記事No6254
投稿日: 2007/09/07(Fri) 14:57
投稿者
> TextBox3 のコントロールを、ワーカースレッドから操作することはできません。
> (VB2005 なら、即座に不正処理の例外が発生するので分かりやすいのですけれどね)

魔界の仮面弁士様、コメントありがとうございます。

ですが実際には、表示させてる値が変わっているので
コントロールできているのですが・・・?

[ツリー表示へ]
タイトルRe^3: マルチスレッドについて
記事No6255
投稿日: 2007/09/07(Fri) 15:28
投稿者Hongliang
> ですが実際には、表示させてる値が変わっているので
> コントロールできているのですが・・・?

それがこの問題のタチの悪いところです。

[ツリー表示へ]
タイトルRe^3: マルチスレッドについて
記事No6256
投稿日: 2007/09/07(Fri) 15:54
投稿者魔界の仮面弁士
BeginInvoke/Invoke メソッドを使いましょう。


> ですが実際には、表示させてる値が変わっているので
> コントロールできているのですが・・・?

残念ながら、「コントロールできることもある」です。
成功する確率が、失敗する確率よりも高かっただけに過ぎません。

ワーカスレッドが TextBox を直接操作するようなことは厳禁です。
メインスレッドに TextBox の操作を依頼するのならば OK ですが。


これは別に、コントロールに限った話ではありません。
たとえば、Form1 上の Private cost As Integer な変数に対し、ワーカースレッドから、
 cost += newValue
のように、金額を newValue 円ずつ増やしていくような単純な処理さえも、
マルチスレッド処理では NG となります。


マルチスレッド処理では、(失敗するタイミングがシビアな)再現性の低いバグを
作りこんでしまう危険性が高いので、十分に注意してください。


# もし、VB.NET のマルチスレッド化に関する資料が必要なら。
# 下記の第7章あたりを読んでみると良いかも。
# http://www.amazon.co.jp/o/ASIN/4798102164

[ツリー表示へ]
タイトルRe^4: マルチスレッドについて
記事No6257
投稿日: 2007/09/07(Fri) 16:12
投稿者
Hongliang様、魔界の仮面弁士様、コメントありがあとうございます。

> BeginInvoke/Invoke メソッドを使いましょう。
これについては、調べて挑戦してみます。

>
> > ですが実際には、表示させてる値が変わっているので
> > コントロールできているのですが・・・?
>
> 残念ながら、「コントロールできることもある」です。
> 成功する確率が、失敗する確率よりも高かっただけに過ぎません。
>
> ワーカスレッドが TextBox を直接操作するようなことは厳禁です。
> メインスレッドに TextBox の操作を依頼するのならば OK ですが。
>
>
> これは別に、コントロールに限った話ではありません。
> たとえば、Form1 上の Private cost As Integer な変数に対し、ワーカースレッドから、
>  cost += newValue
> のように、金額を newValue 円ずつ増やしていくような単純な処理さえも、
> マルチスレッド処理では NG となります。
>
>
> マルチスレッド処理では、(失敗するタイミングがシビアな)再現性の低いバグを
> 作りこんでしまう危険性が高いので、十分に注意してください。
ワーカースレッドから、直接Form1のTextBoxを操作するのは、無理と考えた方がいいみたいですね。

> # もし、VB.NET のマルチスレッド化に関する資料が必要なら。
> # 下記の第7章あたりを読んでみると良いかも。
> # http://www.amazon.co.jp/o/ASIN/4798102164
ご紹介していただいた本は、先日購入しようと思い会社の近くの本屋に行ったのですが
ありませんでした(T_T)
ネットで購入しようと思います。

また、BeginInvoke/Invoke で解らない事がありましたら、また質問させていただきたいと思います。
その時はよろしくお願いいたします。

ありがとうございましたm(__)m

[ツリー表示へ]
タイトル結果のご報告
記事No6265
投稿日: 2007/09/10(Mon) 16:45
投稿者
Hongliang様、魔界の仮面弁士様

結果のご報告です。

アドバイスを頂いてから、私なりにいろいろと調べてできるようになりました。
最初、
Dim dlg1 As New TextBox1_DispDelegate(AddressOf TextBox1_Disp)
Dim str As String
TextBox1.Invoke(dlg1, New Object() {str})
とやっていたのですが、やはり途中で止まってしまいました。
さらに調べて
dlg1.DynamicInvoke(New Object() {str})
としたら、途中で止まったりせず動くようになりました。

Hongliang様、魔界の仮面弁士様、ありがとうございました。

[ツリー表示へ]