VisualBasicでもDelegate処理-非同期処理のお浚い

|

前回、デリゲートの機能の一つを浚いましたので、今回はDelegateの二つ目の機能である「非同期処理」について浚ってみる事に。

色々と調べてみると、VBコンパイラはDelegateを宣言すると、自動的にBeginInvokeメソッドとEndInvokeメソッドを生成してくれます。

UIがフリーズしないようにする為の非同期処理は、この二つのメソッドにより可能となる様です。

【非同期呼出しの勘所】

・呼び出し方:BeginInvoke(デリゲートの仮引数 *1、コールバックデリゲート、Object) As IAsyncResult

・BeginInvoke メソッドを使用する事により、デリゲート経由で呼び出すメソッドを別のスレッドで非同期に実行。

・コールバックメソッドの中で EndInvoke メソッドを呼び出し、メモリリークの可能性を回避。

・デリゲート経由でメソッドを呼び出すと、CLRが管理しているスレッドプールに実行を依頼。その後、制御が直ぐに戻ってくるので呼び出したメソッドとは関係無く、(終了を待たずに)プログラムを先に進める事が可能。

・コールバックメソッドはスレッドプール側で実行されるので、UIを直接更新する事は不可。

*1:引数の数はデリゲート宣言の仮引数に基づくので、お試しソースでは一つ。


<注意点>

・メソッドのシグネチャは同一である事が重要。コールバックメソッドも対応するデリゲートの引数の数と型、戻り値の型に合わせる事。

・BeginInvoke のデリゲート呼出しは非同期で行われる(別スレッド)ので、メソッド呼出し後、直ぐに呼び出し元スレッドに制御が戻る。今回の場合、メッセージボックスのタイトルは「Asynchronous Test」「Asynchronous Method」の順で表示される。

・Windowsフォームは、別スレッドからのUI操作は保障されていないので、②の Label1.Text のコメントを外して実行すると、「有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'Label1' がアクセスされました。」と例外が発生する。


お試し環境
  Windows7 64bit Edition
  Visual Basic 2008 AnyCPU対象


/*-------------------------------- お試し結果 ------------------------------*/

・ボタン2を押すと、直ぐに表示

Asynchronous Test のタイトルで表示

・その約2秒後に表示

Asynchronous Method のタイトルで表示

/*----------------------------------------------------------------------------*/


/*----------------------------  お試しソース -------------------------------*/

Public Class Form3

    Delegate Sub dlgtDispRpt(ByVal msg As String) ' ①非同期 デリゲートの定義

    Private Sub DisplayRpt(ByVal msg As String) ' ②非同期 デリゲートで呼び出すメソッドの作成
        System.Threading.Thread.Sleep(2000)
        '        Label1.Text = "Asynchronous Method" & " and " & msg
        MsgBox(msg, MsgBoxStyle.Information, "Asynchronous Method")
    End Sub

    Private Sub dispCallback(ByVal ar As IAsyncResult) ' コールバックメソッド
        Dim arDispRpt As dlgtDispRpt

        arDispRpt = CType(ar.AsyncState, dlgtDispRpt)
        arDispRpt.EndInvoke(ar)
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim dispRpt As dlgtDispRpt ' ③非同期 デリゲート型の変数を宣言
        Dim ar As IAsyncResult

        dispRpt = New dlgtDispRpt(AddressOf DisplayRpt) ' ④非同期 デリゲート型変数にメソッドを登録
        ar = dispRpt.BeginInvoke("See actions", New AsyncCallback(AddressOf dispCallback), dispRpt) ' ⑤非同期 デリゲートの呼び出し

        MsgBox("See actions", MsgBoxStyle.Information, "Asynchronous Test")
    End Sub

End Class

/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*============================================================================*/

このブログ記事について

このページは、微禄が2022年4月24日 07:24に書いたブログ記事です。

ひとつ前のブログ記事は「VisualBasicでもDelegate処理-使い方のお浚い」です。

次のブログ記事は「VisualBasicでもDelegate処理-別スレッドからUI更新のお浚い」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

お気に入りリンク

NOP法人 アジアチャイルドサポート 最も大切なボランティアは、自分自身が一生懸命に生きること