none
ステップ 7 ハンズオン : 非同期処理を使ったパフォーマンスの向上 のプログラムでエラー発生 RRS feed

  • 質問

  • こんにちは、初心者です。

    Visual Studio 2008 Version 9.0.30729.1 SP     OS:Vista Home Premium SP2  で勉強中です。

    http://msdn.microsoft.com/ja-jp/events/dd229369.aspx

    ステップ 7 ハンズオン : 非同期処理を使ったパフォーマンスの向上のサンプルプログラムでエラーが発生しました。

    マイクロソフトに直に問い合わせる方法が見つからなかったので、このフォーラムに質問させて頂きます。

    エラー内容:非同期処理を選択して開始ボタンを押すと

    Private Sub additem(ByVal strItem As String)
            Me.ListBox1.Items.Add(strItem)
        End Sub

    で、「有効でないスレッド間の操作:コントロールが作成されたスレッド以外のスレッドからコントロール'ListBox1'がアクセスされました。」というエラーが発生しました。

    Step6の章の最後に以下の説明がありました。

    さて、ここで大事な点があります。BeginInvoke で非同期処理を実行して処理が完了したら必ず、EndInvoke を実行しなければならないという事です。EndInvoke を実行しないとメモリーリークが発生する可能性がありますので、忘れずに実装しましょう。EndInvoke を実行するためのオブジェクトは完了通知のためのメソッドに渡されるオブジェクトから取り出すことができます。引数で渡されたオブジェクトをキャストし て、EndInvoke を実行しましょう。

    これが原因なのかと思い、フォーラムで検索したところ、

    http://social.msdn.microsoft.com/Forums/ja-JP/csharpgeneralja/thread/f2cbd0d8-b0e3-407d-9a3c-fb5a593b8b8e

    タイトル:Control.EndInvoke は呼ばなくてもよい?

    を読ませて頂きました所、今回のエラーの原因にはならないのではと推測しました。

    なにぶん、初心者なのでエラー内容から原因を特定できなくて困っています。

    このサンプルプログラムを完成するためのご支援をお願いします。

    (もし、EndInvokeを追記するにしても、前述の説明だけでコード化する知識もありません。)

    よろしくお願いします。

    以下にコードを添付します。

    Public Class Form1

        Private Sub myProc()
            Dim i As Integer
            For i = 1 To 5
                ' 以下のコードを追加
                If Me.optDoEvents.Checked Then
                    Application.DoEvents()
                End If
                ' ここまで

                System.Threading.Thread.Sleep(500)
                Me.additem(i.ToString() & "回目の処理完了 " & Now.ToLongTimeString())
            Next
        End Sub

        Private Sub additem(ByVal strItem As String)
            Me.ListBox1.Items.Add(strItem)
        End Sub

        Private Delegate Sub mydelegate()

        Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click

            Dim dlgMyProc As New mydelegate(AddressOf myProc)

            Me.ListBox1.Items.Clear()
            Me.additem("start")

            If Me.optDelegate.Checked Then
                dlgMyProc.BeginInvoke(AddressOf comp, dlgMyProc)
            Else
                Me.myProc()
                Me.additem("end")
            End If

        End Sub

        Private Sub comp(ByVal a As IAsyncResult)
            Additem("end")
        End Sub
    End Class

    2010年7月13日 23:58

回答

  • こんにちは。

    ページの最後に注意!

    ----------
    しかし、このアプリケーションには問題が内在されています。Windows アプリケーションには 「window に対する操作はウィンドウを生成したスレッドから行わなければならない」という原則があります。それに対して、現在はウィンドウとは別のスレッドからリス トボックスに書き込む処理を行っています。一見正しく動いているように見えますが、その動作は保障されたものではありません。そのためこの部分を修正してやる必要があります。
    ----------

    とあって

    次は 『非同期処理の注意点』について説明します。

    なので、期待通りってことなのではないでしょうか。


    K.Oumi

    • 編集済み K.Oumi 2010年7月14日 2:10 ちょっとしたミス修正
    • 回答の候補に設定 山本春海 2010年7月23日 8:53
    • 回答としてマーク 山本春海 2010年7月29日 4:47
    2010年7月14日 2:09