タスク5.1 - カスタム固定リソースを作成する

タスクの概要

このチュートリアルタスクでは、オブジェクトの処理フローを使用して固定リソースのカスタムロジックを設計する方法を学習します。基本FRオブジェクトをモデルに追加し、バッチ内のフローアイテムを受け取って​処理するオブジェクトの処理フローに添付します。また、このチュートリアルでは、カスタム固定リソースの設計の際によく見られる問題や失敗についても取り扱います。作業が完了すると、モデルは次の画像のようになります。

アイテムの受け取りとリリース

基本FRオブジェクトは空白のスレートです。つまり、アイテムの受け取りやリリースを行う独自のロジックを持たないことを意味します。オブジェクトの処理フローを作成して、このロジックを基本FRオブジェクトに明示的に追加する必要があります。このロジックを処理するには、イベントリスニングのアクティビティで[アイテムを受け取る]と[アイテムをリリース]のピックリストを使用します。

標準的な固定リソースを処理フロー(キューやプロセッサなど)に添付する場合は、[アイテムを受け取る]と[アイテムをリリース]のピックリストを使用しないことに注意してください。代わりに、[ポートを閉じる]と[ポートを開く]のピックリストを使用します。コンテキストにおけるピックリストの例については、「チュートリアル2 - タスクシーケンス」を参照してください。

ステップ1 3Dモデルを構築する

このステップでは、基本的な3Dモデルを構築します。作業が完了すると、3Dモデルは次の画像のようになります。

このモデルを構築するには:

  1. ライブラリから次のオブジェクトをドラッグします。
    • 1つの[ソース
    • 2つの[キュー
    • 1つの[基本FR
    • 1つの[オペレーター
    • 3つの[プロセッサ
    • 1つの[シンク
    • 1つの[平面
  2. このステップのはじめに画像で示したレイアウトとほぼ同じレイアウトになるように、オブジェクトを移動します。
  3. 分かりやすくするために、オブジェクトの名前を次のように変更します。
  4. オブジェクト 新しい名前
    Source1 ソース
    BasicFR1 バッチ
    Operator1 オペレーター
    Sink1 シンク
    平面 休憩室
  5. バッチ]をクリックして選択します。
  6. [プロパティ]で、バッチのサイズを次のように変更します。
    • Xサイズ3.00
    • Yサイズ1.50
    • Zサイズ0.50
  7. 次のポート接続(A接続)を作成します。
    • ソース]から[Queue1]に
    • Queue1]から[バッチ]に
    • バッチ]から[Processor1]に
    • Processor1]から[Queue2]に
    • Queue2]から[Processor2]と[Processor3]に
    • Processor2]と[Processor3]を[シンク]に
  8. Queue2]から[オペレーター]へのセンターポート接続(S接続)を作成します。
  9. Queue2]をクリックして、右側でそのプロパティを開きます。
  10. 出力]セクションで、[輸送を使用]チェックボックスをオンにして、このキューでセンターポートに接続されたオペレーターが使用されることを確認します。

このセクションの冒頭に表示した画像のようにモデルがなっていることを確認します。

ステップ2 オブジェクトの処理フローにアクティビティを追加する

このステップでは、オブジェクトの処理フローにアクティビティを追加して、カスタムの固定リソースを構築します。この固定リソースでは、3つのフローアイテムを受け取り、アイテムをバッチ処理し、次の下流リソースにアイテムをリリースします。作業が完了すると、処理フローは次の画像のようになります。

現時点では、これらのアクティビティの追加と処理フローへの接続のみを行います。後のステップで、プロパティを編集して機能を追加します。

これらのアクティビティを追加して接続するには:

  1. メインツールバーで[処理フロー]ボタンをクリックして、メニューを開きます。[オブジェクトの処理フローを追加]をポイントしてから、[空白]を選択します。
  2. [プロパティ]の[処理フローの名前]ボックスで、現在のテキストを削除し、処理フローの名前を「BatchLogic」に変更します。
  3. ライブラリから、[スケジュールソース]アクティビティ([トークンの作成]の下)を追加します。
  4. ライブラリから、[イベントを待つ]アクティビティを追加し、このアクティビティの最後に[遅延]アクティビティを追加してスタックブロックを作成します。
  5. 前のステップを2回繰り返して、同じスタックブロックをあと2つ作成します。
  6. ライブラリから、次のアクティビティを追加して、スタックブロックをあと1つ作成します。
    • 遅延]アクティビティ([ベーシック]の下)
    • 3つの[イベントを待つ]アクティビティ([ベーシック]の下)
  7. 分かりやすくするために、これらのアクティビティの名前を次のように変更します。
  8. アクティビティ 新しい名前
    ソース ソース:シミュレーションを開始
    最初のイベントを待つ イベントを待つ:アイテム1を受け取る
    最初の遅延 遅延:アイテム1を処理
    2番目のイベントを待つ イベントを待つ:アイテム2を受け取る
    2回目の遅延 遅延:アイテム2を処理
    3番目のイベントを待つ イベントを待つ:アイテム3を受け取る
    3回目の遅延 遅延:アイテム3を処理
    4回目の遅延 遅延:すべてのアイテムを処理
    4番目のイベントを待つ イベントを待つ:アイテム1をリリース
    5番目のイベントを待つ イベントを待つ:アイテム2をリリース
    6番目のイベントを待つ イベントを待つ:アイテム3をリリース
  9. 次のアクティビティからコネクターを作成します。
    • ソース:シミュレーションを開始]から[イベントを待つ:アイテム1を受け取る]アクティビティに
    • 遅延:アイテム1を処理]から[イベントを待つ:アイテム2を受け取る]アクティビティに
    • 遅延:アイテム2を処理]から[イベントを待つ:アイテム3を受け取る]アクティビティに
    • 遅延:アイテム3を処理]から[遅延:すべてのアイテムを処理]アクティビティに
  10. イベントを待つ:アイテム3をリリース]から[イベントを待つ:アイテム1を受け取る]アクティビティにループするコネクターを作成します。

シミュレーションモデルを保存することをおすすめします。

ステップ3 受け取りアクティビティを編集する

このステップでは、アイテムの受け取りを扱う処理フローのアクティビティのプロパティを編集します。最初に[バッチ]をインスタンスとして処理フローに添付する必要があります。これにより、currentキーワードを使用してバッチを動的に参照することができるようになります。また、より複雑なモデルを簡単に拡張できるようになります。各オブジェクトの処理フローをコピーせずに、追加の基本FRオブジェクトを処理フローへの添付として追加できます。

各アクティビティの機能の概要を次に示します。

アクティビティ 説明
ソース:シミュレーションを開始 [スケジュールソース]アクティビティでは、シミュレーションの開始直後にトークンを1つ作成し、そのトークンを[イベントを待つ]アクティビティに送信します。このトークンを作成した後は、追加のトークンは作成されません。トークンは、シミュレーションが終了するまで他のアクティビティをループし続けます。このアクティビティにはデフォルトのプロパティを使用します。
イベントを待つ:アイテムを受け取る [イベントを待つ]アクティビティはイベントリスニングのアクティビティです。つまり、リスニング対象のイベントが発生するまで、トークンはこのアクティビティで待機します。この処理フローでは、最初の3つの[イベントを待つ]アクティビティが、[エントリ時]イベントのバッチをリッスンします。バッチは基本FRオブジェクトなので、フローアイテムを受け取るように明示的に指示する必要があります。バッチがフローアイテムを受け取ると、イベントをトリガーしたフローアイテムへの参照を格納する「Item1」、「Item2」または「Item3」という名前のラベルを割り当てます。
遅延:処理時間 バッチが各フローアイテムを処理する時間を表すために、5秒の遅延を追加します。

これらのプロパティを編集するには:

  1. 処理フローの空白スペースをクリックして、何も選択されていないことを確認します。[クイックプロパティ]の[処理フローインスタンス]グループで[エンティティの追加 (インスタンス)]リストを見つけます。[サンプラー]ボタン をクリックして、サンプリングモードに入ります。
  2. 3Dモデルで、[バッチ]をクリックして、サンプリングします。
  3. イベントを待つ:アイテム1を受け取る]アクティビティをクリックして選択します。[プロパティ]の[オブジェクト]ボックスに「current (No Instance)」が表示されていることを確認します。
  4. イベント]ボックスの横にある[サンプラー]ボタンをクリックして、サンプリングモードに入ります。
  5. 3Dモデルで、[バッチ]をクリックして、メニューを開きます。[エントリ時]を選択して、このイベントをサンプリングします。
  6. 次に、[ラベル照合/割り当て]テーブルを探します。[ラベル名]列の[入るアイテム]行に「Item1」と入力します。
  7. オペレーション]列のセルをクリックして、メニューを開きます。[割り当てる]を選択します。
  8. リスナーの初期化時]ボックスの横にある[追加]ボタン をクリックして、メニューを開きます。[コントロール]をポイントし、次に[基本FR]、次に[アイテムを受け取る]をポイントしてピックリストオプションを開きます。
  9. デフォルト設定を使用し、ピックリストオプションが次の画像と同様であることを確認します。
  10. イベントを待つ:アイテム2を受け取る]と[イベントを待つ:アイテム3を受け取る]アクティビティに対してステップ4~11を繰り返します(ただし、ステップ8でラベル名「Item2」と「Item3」を使用)。
  11. 遅延:アイテム1を処理]アクティビティをクリックして選択します。[プロパティ]の[遅延時間]ボックスで、現在のテキストを削除し、「5.00」と入力します。
  12. 遅延:アイテム2を処理]と[遅延:アイテム3を処理]アクティビティで前のステップを繰り返します。

シミュレーションモデルを保存することをおすすめします。

ステップ4 リリースアクティビティを編集する

このステップでは、処理フローでアイテムのリリースを扱うアクティビティのプロパティを編集します。各アクティビティの機能の概要を次に示します。

アクティビティ 説明
遅延:処理時間 バッチが各フローアイテムを処理する時間を表すために、5秒の遅延を追加します。
イベントを待つ:アイテムをリリース 最後の3つの[イベントを待つ]アクティビティは、最初の3つの[イベントを待つ]アクティビティのミラーイメージです。これらの3つのアクティビティは、[終了時]イベントの[バッチ]をリッスンします。バッチは基本FRオブジェクトなので、処理後にフローアイテムをリリースするように明示的に指示する必要があります。バッチが正しいアイテムをリリースするようにするには、最初の3つの[イベントを待つ]アクティビティによって作成された「Item1」、「Item2」、または「Item3」というラベルを参照する必要があります。

これらのプロパティを編集するには:

  1. 遅延:すべてのアイテムを処理]アクティビティをクリックして選択します。[プロパティ]の[遅延時間]ボックスで、現在のテキストを削除し、「10.00」と入力します。
  2. イベントを待つ:アイテム1をリリース]アクティビティをクリックして選択します。[プロパティ]の[オブジェクト]ボックスに「current (No Instance)」が表示されていることを確認します。
  3. イベント]ボックスの横にある[サンプラー]ボタンをクリックして、サンプリングモードに入ります。
  4. 3Dモデルで、[バッチ]をクリックして、メニューを開きます。[終了時]を選択して、このイベントをサンプリングします。
  5. リスナーの初期化時]ボックスの横にある[追加]ボタン をクリックして、メニューを開きます。[コントロール]をポイントし、次に[基本FR]、次に[アイテムをリリース]をポイントしてピックリストオプションを開きます。
  6. リリースするアイテムを指定:]ボックスで、現在のテキストを「token.Item1」に変更します。
  7. イベントを待つ:アイテム2をリリース]と[イベントを待つ:アイテム3をリリース]アクティビティに対してステップ3~8を繰り返します(ただし、ステップ8でラベル名「token.Item2」と「token.Item3」を使用)。

シミュレーションモデルを保存することをおすすめします。

ステップ5 モデルをテストする

気付いていないかもしれませんが、カスタム固定リソースには、この時点でいくつかの問題があります。モデルをリセットして実行し、問題点を自分で見つけられるか確認してください。分からない場合は、このステップの残りの部分で問題について説明します。

それでも問題が分からない場合は、次を試してください。

  1. モデルをリセットして実行します。
  2. バッチ]でフローアイテムを[Processor1]にプッシュするまで待ちます。
  3. シミュレーションモデルを一時停止し、[Processor1]のフローアイテムの1つを移動してみます。実際にプロセッサには3つのアイテムがあることがわかります。

ここには2つの問題があります。まず、[バッチ]でボックスが表示されていません。処理フローでは明示的にボックスの位置を設定していないため、バッチによって飲み込まれて表示されません。[バッチ]で表示されている場合は、3つのフローアイテムがすべて同じスペースに表示されます(Processor1と同様)。これは、FlexSimがオブジェクトを自動でオフセットする方法と関係があります。

次に、[バッチ]が3つのフローアイテムを同時にリリースし、次のバッチの先頭にジャンプすることが確認できるでしょう(こちらの方が重要です)。フローアイテムを同時にリリースすると、プロセッサでは3つのアイテムを同時に処理しますが、これは間違った動作です。この動作は、FlexSimのイベント処理の仕組みによって発生します。

次の2つのステップで、この2つの問題を解決する方法を学びます。

ステップ6 フローアイテムのビジュアルを変更する

このステップでは、[バッチ]オブジェクトのフローアイテムのビジュアルの問題を修正します。これは、バッチでアイテムを受け取る方法をコントロールするアクティビティブロックに3つの[ビジュアルを変更]アクティビティを(各アイテムに1つ)追加することで解決します。[場所を変更]ピックリストオプションを使用して、[バッチ]アクティビティ内のフローアイテムオフセットを設定します。作業が終了すると、処理フローは次の画像のようになります。

このステップで表示されるFlexScript式の1つは、current.size.z式です。この式では、フローアイテム(バッチ)を含むアイテムのZの位置を取得し、フローアイテムをコンテナオブジェクトの上に配置してオブジェクトに吸収されないようにします。

バッチと相対するフローアイテムのビジュアルを変更するには:

  1. イベントを待つ:アイテム1を受け取る]と[遅延:アイテム1を処理]のアクティビティを区別する線の上にマウスを移動します。線が黄色に変わったら、線をダブルクリックして[クイックライブラリ]を開きます。
  2. ビジュアル]グループで[ビジュアルを変更]ボタン をクリックし、このアクティビティを追加します。
  3. このステップを繰り返して、次の2つのスタックブロック間にも[ビジュアルを変更]アクティビティを挿入します。
  4. 分かりやすくするために、これらのアクティビティの名前を次のように変更します。
  5. アクティビティ 新しい名前
    最初のビジュアル変更 ビジュアルを変更:アイテム1の場所
    2回目のビジュアル変更 ビジュアルを変更:アイテム2の場所
    3回目のビジュアル変更 ビジュアルを変更:アイテム3の場所
  6. ビジュアルを変更:アイテム1の場所]をクリックして選択します。[プロパティ]の[ビジュアルを変更]ボックスの横にある[追加]ボタンをクリックしてメニューを開きます。[場所を設定]を選択して、ピックリストオプションの一部を開きます。
  7. ピックリストオプションは次のように設定します。
    • オブジェクト]ボックスに「token.Item1」と入力します。
    • Xの場所]ボックスに「0.6」と入力します
    • Yの場所]ボックスに「-0.8」と入力します
    • Zの場所]ボックスに「current.size.z」と入力します

  8. 前のステップを繰り返し[ビジュアルを変更:アイテム2の場所]を設定しますが、今回は次の設定を使用します。
    • オブジェクト]ボックスに「token.Item2」と入力します。
    • Xの場所]ボックスに「1.5」と入力します
    • Yの場所]ボックスに「-0.8」と入力します
    • Zの場所]ボックスに「current.size.z」と入力します

  9. 前のステップを繰り返し[ビジュアルを変更:アイテム3の場所]を設定しますが、今回は次の設定を使用します。
    • オブジェクト]ボックスに「token.Item3」と入力します。
    • Xの場所]ボックスに「2.4」と入力します
    • Yの場所]ボックスに「-0.8」と入力します
    • Zの場所]ボックスに「current.size.z」と入力します

モデルを実行して、[バッチ]でフローアイテムがどのようにスタックされるかを確認してください。

ステップ7 処理フローに息継ぎアクティビティを追加する

モデルをテストしたステップから思い出せるように、バッチには、すべてのフローアイテムを同時に下流プロセッサにリリースするという問題があります。この問題は、FlexSimのイベント処理の仕組みによって発生します。プロセッサでは、次のアイテムを受け取る準備ができたら、入力ポートを開き、最初のアイテムがバッチを終了するようにします。バッチの[終了時]イベントが起動すると、残りの[イベントを待つ]アクティビティも同様に起動し、すべてのアイテムを同時にリリースします。このイベントリスニングロジックはすべて、プロセッサでアイテムを受け取り、入力ポートを閉じたことが分かる前に発生します。したがって、プロセッサの入力ポートが開いている間は、すべてのアイテムがリリースされ、すぐに終了します。

他のシナリオでも、これと同じ問題が発生する可能性があります。処理フローツール内では通常、[イベントを待つ]または[イベントトリガーソース]でリッスンイベントが起動する場合に発生し、そのあとに元のトリガーされたイベントとそれに続くイベントトリガーロジックの間で遅延が発生することなく、モデルでイベントが起動する可能性のある1つ以上のアクティビティが続きます。ロジックが短期間に発生するため、元のイベントが「息継ぎ」をして処理中の作業を終了する時間が与えられません。このような場合、0秒間遅延するように設定された[遅延]アクティビティである[息継ぎ]アクティビティを追加して問題を解決できます。これにより、トークンが移動する前に、元のトリガーイベントで行っていた処理を完了できます。

作業が終了すると、処理フローは次の画像のようになります。

これらの[息継ぎ]アクティビティを追加するには:

  1. イベントを待つ:アイテム1をリリース]と[イベントを待つ:アイテム2をリリース]アクティビティを区別する線の上にマウスを移動します。線が黄色に変わったら、線をダブルクリックして[クイックライブラリ]を開きます。
  2. ベーシック]グループの下の[遅延]ボタン をクリックし、このアクティビティを追加します。
  3. これらのステップを繰り返して、2つの[遅延]アクティビティを[イベントを待つ:アイテム2をリリース]と[イベントを待つ:アイテム3をリリース]アクティビティの後に追加します。
  4. 分かりやすくするために、これらのアクティビティの名前を次のように変更します。
  5. アクティビティ 新しい名前
    最初の遅延 息継ぎ1
    2回目の遅延 息継ぎ2
    3回目の遅延 息継ぎ3
  6. [プロパティ]で、3つの[息継ぎ]アクティビティすべての[遅延時間]を「0.00」に設定します。

モデルをリセットして実行してみてください。今度は、フローアイテムが一度にバッチを離れるのではなく一度に1つずつ離れることが分かります。

少々直観に反しているように思われるかもしれませんが、アイテムを受け取ったりリリースしたりするには[イベントを待つ]アクティビティを使用する必要があります。[カスタムコード]アクティビティのreleaseitem()コマンドをそれぞれの[イベントを待つ:アイテムをリリース]アクティビティの前に使用する方が簡単ではないかと疑問に思われるかもしれません。

このアプローチの問題点は、コマンドの実行が完了する前にアイテムが実際に終了する可能性があることです。トークンが[イベントを待つ:アイテム1をリリース]アクティビティに到達するまでに、アイテム1はすでに終了しています。リッスンされるイベントはすでに起動されているため、トークンは永久に待機状態になります。

この問題の解決策は、[イベントを待つ]アクティビティでOnListenerInitializedトリガーを使用することです。これにより、正しい順序でロジックが起動されるように保つことができます。最初にイベントリスニングロジックを実行した後、アイテムを受け取り/リリースするロジックを実行できます。

結論

これまで、処理フローツールでカスタム固定リソースのロジックを作成する方法について学習しました。次のタスクでは、カスタムタスク実行者のロジックを作成する方法を学習します。チュートリアルタスク5.2 - カスタムタスク実行者を作成するに進みます。