SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Workflow Foundation 4が導く新しい開発スタイル

「Workflow Foundation 4」の中心~アクティビティの作成

Workflow Foundation 4が導く新しい開発スタイル(2)

非同期処理を行うAsyncCodeActivity

 WF 4ではParallel~と名前の付いたアクティビティが用意されているので、非同期処理を行えるように思えますが実際には皆さんがイメージされるであろうマルチタスキング的な非同期処理は行うことができません。Parallelアクティビティの実際の挙動は、次のようになります。

プロジェクトの参照設定
プロジェクトの参照設定

 何かしらの重たい処理が実行され、アクティビティ内部にて待機状態が発生します。WFランタイムは待機状態を検知すると、待機している他のアクティビティへと制御を遷移させます。同様に遷移先で待機状態が発生すると、さらに他の待機アクティビティへと遷移していきます。実際には待機状態に遷移した際に、WFランタイムが次にキューイングされている処理を判断し実行を遷移させています。このように非同期処理と言っても、特定のアクティビティでワークフロー全体が待機状態に陥らないようにするためのものとなっています。

 本当の意味で並列処理を行うためには、アクティビティ内部でスレッドを作成し処理を実行するのと、制御を受け取ったら即座に制御をWFランタイムに戻してあげるようにすることで対応が可能です。細かい実装については私のBlog記事にてまとめてあるので、参考にしてみてください。

 しかし、重い処理をアクティビティに行わせ、ワークフローの実行スレッドを長期にわたり押さえてしまうと、問題のあるケースがやはり発生します。そのような場合に利用するのが非同期処理を行うためのAsyncCodeActivityです。これはアクティビティの処理を非同期にて行うことが可能になります。また非同期で行う際にはアイドル状態になることもあるかと思いますが、その際にWFランタイムによる永続化やアンロードが行われないようにすることも可能です。

 AsyncCodeActivityの利用サンプルを次に示します。

アクティビティ部分のコード(Visual Basic)
Imports System.Activities
Public Class SampleAsyncActivity
    Inherits AsyncCodeActivity

    Private Delegate Sub AsyncOutputConsole()

    Protected Overrides Function BeginExecute(context As System.Activities.AsyncCodeActivityContext, callback As System.AsyncCallback, state As Object) As System.IAsyncResult
        Dim outDel = New AsyncOutputConsole(AddressOf OutputConsole)
        context.UserState = outDel
        Return outDel.BeginInvoke(callback, state)
    End Function

    Protected Overrides Sub EndExecute(context As System.Activities.AsyncCodeActivityContext, result As System.IAsyncResult)
        Dim outDel As AsyncOutputConsole = context.UserState
        '非同期処理終了後の何らかの処理
    End Sub

    Private Sub OutputConsole()
        Console.WriteLine("非同期アクティビティからの出力です")
    End Sub

End Class
ホスティング部分のコード(Visual Basic)
Imports System.Activities
Module Module1

    Sub Main()
        Dim act As New SampleAsyncActivity
        Dim wfApp As New WorkflowApplication(act)
        wfApp.Run()

        'タイミングが重なるようにウェイトをかける(環境によりウェイトは変化させてください)
        System.Threading.Thread.Sleep(31)
        For cnt = 0 To 100
            Console.WriteLine("ホスト側からの出力です")
        Next

        Console.ReadLine()
    End Sub
End Module
アクティビティ部分のコード(C#)
using System;
using System.Activities;
namespace SampleAsyncActivity
{
    class SampleAsyncActivity: AsyncCodeActivity
    {
        private delegate void AsyncOutputConsole();

        protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
        {
            var outDel = new AsyncOutputConsole(OutputConsole);
            context.UserState = outDel;
            return outDel.BeginInvoke(callback, state);
        }

        protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
        {
            var outDel = (AsyncOutputConsole)context.UserState;
            //非同期処理終了後の何らかの処理
        }

        private void OutputConsole()
        {
            Console.WriteLine("非同期アクティビティからの出力です");
        }
    }
}
ホスティング部分のコード(C#)
using System;
using System.Activities;
using System.Activities.Statements;
namespace SampleAsyncActivity
{
    class Program
    {
        static void Main(string[] args)
        {
            var act = new SampleAsyncActivity();
            var wfApp = new WorkflowApplication(act);
            wfApp.Run();

            //タイミングが重なるようにウェイトをかける(環境によりウェイトは変化させてください)
            System.Threading.Thread.Sleep(31);
            for (int cnt = 0; cnt < 100; cnt++)
            {
                Console.WriteLine("ホスト側からの出力です");
            }

            Console.ReadLine();
        }
    }
}
AsymcCodeActivityの実行結果
AsyncCodeActivityの実行結果

 実行するとホスト側の出力とワークフロー側の出力が混じったこのような形で出力されます。サンプルとして用意したのは、単純に標準出力に文字を出力するアクティビティです。今回の例はあまり非同期処理に適したものではありませんが、ファイル処理やデータベース処理など非同期で行うのが望ましい処理は多くの場面で起こりえます。そのような場合は、AsyncCodeActivityを利用した非同期アクティビティを作成することで、WFランタイムの動作に影響を与えることなくスムーズに動作させることが可能になります。

次のページ
ブックマークによる入力待機など高機能を利用できるNativeActivity

修正履歴

この記事は参考になりましたか?

Workflow Foundation 4が導く新しい開発スタイル連載記事一覧

もっと読む

この記事の著者

小尾 智之(オビ トモユキ)

地方企業に勤めるインディープロレス好きなエンジニア。VB + SQL Server のシステム構築を主な業務としていましたが、元々の性格もあり色々な物に目移り中。Ahf というハンドルネームで所属する北海道の技術コミュニティ CLR/H(http://clr-h.jp) での活動など行っていましたが、最近か...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/6652 2012/07/13 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー