// <summary>ソースコード：演算中のマルチスレッド制御を行うクラス</summary>
// <author>CommonMP</author>

using System;
using System.Threading;
using System.Collections.Generic;
using System.Text;

using CommonMP.HYSSOP.Interface.HSController;
using CommonMP.HYSSOP.Interface.HSSimulator;
using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;
using CommonMP.HYSSOP.CoreImpl.HSData;

namespace CommonMP.HYSSOP.CoreImpl.HSController
{
    /// <summary><para>class outline:</para>
    /// <para>演算中のマルチスレッド制御を行う</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
    /// </remarks>
    public class HySSimThreadController : HySSysUnit, HySSimThreadCtl
    {
        /// <summary>シミュレーター</summary>
        protected HySSimulatorRoot m_csSimulator;

        /// <summary>シミュレーション制御</summary>
        protected HySControllerRoot m_csController = null;

        /// <summary>シミュレーションスケジュール単位</summary>
        protected HySSimScheduleUnit m_csSimScheduleUnit = null;

        /// <summary>イベント待ちQueue </summary>
        protected HySQueue m_csQueue = new HySQueue(16);

        /// <summary>イベントコールバック動作排他</summary>
        protected HySMutex m_csEventCallBackLock = new HySMutex();
        /// <summary>スレッド動作移行過渡処理排他</summary>
        protected HySMutex m_csThreadTransitionLock = new HySMutex();
        /// <summary>スレッド動作状態</summary>
        protected bool m_bThreadStatus = THREAD_NOT_WORK;

        /// <summary>業務に転送するメッセージ</summary>
        protected HySString m_csSndMessage = new HySString("");

        // 常数定義
        /// <summary>スレッド動作せず</summary>
        static protected readonly bool THREAD_NOT_WORK = false;
        /// <summary>スレッド動作中</summary>
        static protected readonly bool THREAD_AT_WORK = true;

        

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySSimThreadController csController = new HySSimThreadController(csSimulator) </para>
        /// </example>
        /// <param name="csSimulator">シミュレーター</param>
        /// <returns>生成インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySSimThreadController(HySSimulatorRoot csSimulator)
        {
            m_csSimulator = csSimulator;
            m_csSimulator.SetSimThreadCtl(this);
        }

        /// <summary><para>method outline:</para>
        /// <para>シミュレーター取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySSimulator csSim = GetSimulator() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySSimulatorRoot GetSimulator()
        {
            return m_csSimulator;
        }

        /// <summary><para>method outline:</para>
        /// <para>演算スケジュール単位クラスを設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetSimScheduleUnit( csSimScheduleUnit ) </para>
        /// </example>
        /// <param name="csSimScheduleUnit">演算スケジュール単位クラス</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void SetSimScheduleUnit(HySSimScheduleUnit csSimScheduleUnit)
        {
            m_csSimScheduleUnit = csSimScheduleUnit;
        }

        /// <summary><para>method outline:</para>
        /// <para>制御クラスを設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetController( csCtl ) </para>
        /// </example>
        /// <param name="csCtl">制御クラス</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void SetController(HySControllerRoot csCtl)
        {
            m_csController = csCtl;
        }
        // ====================================
        // 演算実行
        // ====================================


        /// <summary><para>method outline:</para>
        /// <para>イベントを受け取った時に動作するメソッド</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = EventCallback( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>各実装クラスは受け取ったイベント毎に処理を行う</para>
        /// </remarks>
        public virtual Boolean EventCallback(HySSysEvent csEvent)
        {
            //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::EventCallback", "Wait");
            m_csEventCallBackLock.Wait();   // <-- EventCallBack() の二重起動防止　Ｍｕｔｅｘが必要ではないか？
            //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::EventCallback", "start");
            Boolean bRtn = false;
            long lEventNo = ((HySEventObject)csEvent).GetEventNo();

            
            if (lEventNo == HySEventObject.CMND_MODEL_CONSTRUCTION)
            {   // シミュレーションモデル作成開始指示
                bRtn = this.ModelConstruction(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_INITIALIZE_SIMULATION)
            {   // シミュレーション初期化指示
                bRtn = this.InitializeSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_START_SIMULATION)
            {   // シミュレーション開始指示
                bRtn = this.StartSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_PAUSE_SIMULATION)
            {   // シミュレーション中断指示
                bRtn = this.PauseSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_RESTART_SIMULATION)
            {   // シミュレーション再開指示
                bRtn = this.RestartSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_STOP_SIMULATION)
            {   // シミュレーション強制終了指示
                bRtn = this.StopSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_REPORT_SIMU_PROGRESS)
            {   // シミュレーション計算進捗状況報告指示
                bRtn = this.ReportSimuProgress(csEvent);
            }
            else
            {   // その他のイベント
                bRtn = m_csSimulator.CmdArbitraryEvent(csEvent);
            }
            //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::EventCallback", "end");
            m_csEventCallBackLock.Release();
            //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::EventCallback", "Release");
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>イベントを送る</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = PutEvent( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送るイベント</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>自分からイベントを送信する時に使用する</para>
        /// </remarks>
        /// 
        public virtual Boolean PutEvent(HySSysEvent csEvent)
        {
            ((HySEventObject)csEvent).SetFromSimKind(m_csSimulator.GetSimKind());
            ((HySEventObject)csEvent).SetToSimKind(m_csSimulator.GetSimKind());
            ((HySEventObject)csEvent).SetSuppID((HySID)m_csSimulator.GetID());

            if (m_csSimScheduleUnit != null)
            {
                return m_csSimScheduleUnit.PutEvent(csEvent);
            }
            else
            {
                return m_csController.PutEvent(csEvent);
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>システム終了準備完了判別</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = ExitOK( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : システムExit準備OK　、false : システムExit準備NG</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual Boolean ExitOK()
        {
            if (m_bThreadStatus == THREAD_NOT_WORK)
            {   return true;   }
            else
            { return false; }
        }

        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算完了したという報告</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> NoticeCompleteCalculation( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void NoticeCompleteCalculation()
        {
            //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::NoticeCompleteCalculation", "start");
            HySEventObject csEvent = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_COMPLETE_SIMULATION);
            //csEvent.SetSimKind(m_csSimulator.GetSimKind());
            //csEvent.SetSuppID((HySID)m_csSimulator.GetID());
            csEvent.SetData(m_csSimulator.GetContainer());
            csEvent.SetSubData(this.m_csSndMessage.Clone());
            m_csSndMessage.SetChar(""); // 送信情報クリア
            this.PutEvent(csEvent);

            if (m_csSimScheduleUnit == null)
            {   // スケジュールで動作していない時
                // 計算完了ならば計算終了へ移行
                csEvent = new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_STOP_SIMULATION);
                this.StopSimulation(csEvent);
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算が異常終了したという報告</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> NoticeCalculationAbend( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void NoticeCalculationAbend()
        {
            //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::NoticeCompleteCalculation", "start");
            HySEventObject csEvent = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_SIMULATION_ABEND);
            //csEvent.SetSimKind(m_csSimulator.GetSimKind());
            //csEvent.SetSuppID((HySID)m_csSimulator.GetID());
            csEvent.SetData(m_csSimulator.GetContainer());
            csEvent.SetSubData(this.m_csSndMessage.Clone());
            m_csSndMessage.SetChar(""); // 送信情報クリア
            this.PutEvent(csEvent);

            // 下記にて　スレッドを終了させてはならない　なぜならば　本メソッドをコールする側で既にスレッド終了処理を行っている
            //if (m_csSimScheduleUnit == null)
            //{   // スケジュールで動作していない時
            //    // 計算完了ならば計算終了へ移行
            //    csEvent = new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_STOP_SIMULATION);
            //    this.StopSimulation(csEvent);
            //}
        }

        /// <summary><para>method outline:</para>
        /// <para>内部演算モデル作成処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = ModelConstruction(csEvent) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:正常、false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual Boolean ModelConstruction(HySSysEvent csEvent)
        {
            // PT-003 言語切り替え不具合修正　地域情報をTheadにセット
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CurrentCulture;
            
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ModelConstruction", "start");
            if (m_bThreadStatus == THREAD_AT_WORK)
            {   // スレッドが動作していれば
                HySEventObject csStopEvent = new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_STOP_SIMULATION);
                m_csSimulator.CmdStopSimulation(csStopEvent);
            }
            this.ThreadStop(); // スレッド終了

            Boolean bRtn = m_csSimulator.ModelConstruction(csEvent);

            HySEventObject csRtnObj = null;            

            if (bRtn == true)
            {
                csRtnObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_OK_MODEL_CONSTRUCTION);
            }
            else
            {
                csRtnObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_NG_MODEL_CONSTRUCTION);
            }
            csRtnObj.SetToSimKind(m_csSimulator.GetSimKind());
            csRtnObj.SetSuppID((HySID)m_csSimulator.GetID());
            csRtnObj.SetSubData(this.m_csSndMessage.Clone());

            //★サーバー／クライアント化で追加
            csRtnObj.SetResponseInfo(((HySEventObject)csEvent).GetResponseInfo());
            //★サーバー／クライアント化で追加

            m_csSndMessage.SetChar(""); // 送信情報クリア

            this.PutEvent(csRtnObj);

            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>内部演算モデル作成処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = ModelConstruction( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true:正常、false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual Boolean DeleteSimulator( )
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::DeleteSimulator", "start");

            Boolean bRtn = m_csSimulator.Terminate();
            /*
            m_csSimulator = null;
            m_csController = null;
            m_csSimScheduleUnit = null;
            m_csQueue = null;
            m_csEventCallBackLock = null;
            m_csThreadTransitionLock = null;
            */
            return bRtn;
        }


        /// <summary><para>method outline:</para>
        /// <para>シミュレーションの初期化</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = InitializeSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>
        /// シミュレーション演算中のスレッドからコールしてはならない
        /// 　（EventCallback()以外からのコール禁止）
        /// </para>
        /// </remarks>
        protected virtual Boolean InitializeSimulation(HySSysEvent csEvent)
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::InitializeSimulation", "start");
            Boolean bRtn = true;
            if (m_bThreadStatus == THREAD_AT_WORK)
            {   // スレッドが動作していれば
                m_csSimulator.CmdPauseSimulation(csEvent);  // 計算を中断させる
                bRtn = m_csQueue.PushObject(csEvent);   // 自身に対して、初期化動作を行わせるイベントを発行する

                //========== スレッド見張りは要らない？
                // this.ThreadStopWatchDog(); // スレッド終了見張り
            }
            else
            {   // スレッドが動作していなければ
                GC.Collect(); // 強制　ガベージコレクション
                HySSimulationDataContainer csContainer = m_csSimulator.GetContainer() as HySSimulationDataContainer;

                //★サーバー／クライアント化で追加
                m_csSimulator.SetContainer(csContainer); // データコンテナ設定
                // ★　本来ならば、頻繁にコンテナインスタンスを修正すべきではない。
                //     変更のあった部分のみを　反映させて、インスタンス本体は入れ替えない。（将来の検討課題）
                //★サーバー／クライアント化で追加

                // 時刻設定
                m_csSimulator.SetSimuStartTime(csContainer.GetStartTime());
                m_csSimulator.SetSimuGoalTime(csContainer.GetGoalTime());
                m_csSimulator.SetSimuTime(csContainer.GetSimuTime());
                m_csSimulator.SetSimuDeltaTime(csContainer.GetDeltaTime());
                // 初期化開始
                bRtn = m_csSimulator.CmdInitializeSimulation(csEvent);
            }
            // イベント応答はシミュレーター内部で行う
            //HySEventObject csRtnObj = null;
            //csRtnObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_INITIALIZE_SIMULATION);
            //csRtnObj.SetSimKind(m_csSimulator.GetSimKind());
            //this.PutEvent(csRtnObj);

            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算の開始</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = StartSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>
        /// シミュレーション演算中のスレッドからコールしてはならない
        /// 　（EventCallback()以外からのコール禁止）
        /// </para>
        /// </remarks>
        protected virtual Boolean StartSimulation(HySSysEvent csEvent)
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::StartSimulation", "start");
            if (m_bThreadStatus == THREAD_AT_WORK)
            {   // スレッドが動作していれば
                HySEventObject csStopEvent = new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_STOP_SIMULATION);
                m_csSimulator.CmdStopSimulation(csStopEvent);
            }
            this.ThreadStop(); // スレッド終了
            this.ThreadStopWatchDog(); // スレッド終了見張り

            this.ThreadStart();  // スレッド動作開始 

            return m_csQueue.PushObject(csEvent);
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算の中断</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = PauseSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual bool PauseSimulation(HySSysEvent csEvent)
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::PauseSimulation", "start");
            return m_csSimulator.CmdPauseSimulation(csEvent);
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算の再開</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = RestartSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual Boolean RestartSimulation(HySSysEvent csEvent)
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::RestartSimulation", "start");

            HySSimulationDataContainer csContainer = m_csSimulator.GetContainer() as HySSimulationDataContainer;

            //★サーバー／クライアント化で追加
            //csContainer = ((HySEventObject)csEvent).GetData() as HySSimulationDataContainer;
            //m_csSimulator.SetContainer(csContainer); // データコンテナ設定
            // ★　本来ならば、頻繁にコンテナインスタンスを修正すべきではない。
            //     変更のあった部分のみを　反映させて、インスタンス本体は入れ替えない。（将来の検討課題）
            //★サーバー／クライアント化で追加
           
            // 再設定（終了時刻と刻み幅のみ）
            m_csSimulator.SetSimuGoalTime(csContainer.GetGoalTime());
            m_csSimulator.SetSimuDeltaTime(csContainer.GetDeltaTime());

            if (m_bThreadStatus == THREAD_NOT_WORK)
            {   // スレッドが動作していなければ
                // スレッドを立ち上げて、中断の状態まで持っていく
                this.ThreadStart();
                // 状態を強制的に中断状態にしておく
                m_csSimulator.CmdPauseSimulation(csEvent);
                // 再開を投げる
                return m_csQueue.PushObject(csEvent);
                //return m_csSimulator.CmdRestartSimulation(csEvent);
            }
            else
            {
                return m_csQueue.PushObject(csEvent);
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算の終了</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = StopSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual Boolean StopSimulation(HySSysEvent csEvent)
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::StopSimulation", "start");
            bool bRtn = m_csSimulator.CmdStopSimulation(csEvent);

            this.ThreadStop(); // スレッド終了

            return bRtn;
        }
        
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算進捗状況報告</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = ReportSimuProgress( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual Boolean ReportSimuProgress(HySSysEvent csEvent)
        {
            long lPrgress = 0;
            HySEventObject csRtnEvent = (HySEventObject)csEvent;// new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_REPORT_SIMU_PROGRESS, lPrgress);
                    // 頻繁に呼ばれるイベントは、速度向上のため　new 使用をなるべく防ぐ
            csRtnEvent.SetTo(HySSysEvent.OBJID_BUSIPROCEDURE);
            csRtnEvent.SetEventNo(HySEventObject.NOTICE_REPORT_SIMU_PROGRESS);
            csRtnEvent.SetSubEventNo(lPrgress);
            if (this.m_csSimScheduleUnit != null)
            {
                // Do nothing
            }
            else
            {
                lPrgress = m_csSimulator.GetSimulationProgress(csEvent);
                csRtnEvent.SetSubEventNo(lPrgress);
                csRtnEvent.SetData(this.m_csSimulator.GetSimuTime());
                //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ReportSimuProgress", "    Progress = "+lPrgress.ToString()+"(%)");
            }

            return this.PutEvent(csRtnEvent);
        }
        

        // ====================================
        // スレッド制御
        // ====================================

        /// <summary><para>method outline:</para>
        /// <para>スレッド起動（別スレッドで this.ThreadRun()が動作を開始する）</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ThreadStart() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual void ThreadStart()
        {
            if (m_bThreadStatus == THREAD_NOT_WORK)
            {   // 現在　「スレッド動作せず」状態の場合
                //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadStart", " m_csThreadTransitionLock.Wait()");
                m_csThreadTransitionLock.Wait(); // スレッド動作移行開始
                if (m_bThreadStatus == THREAD_NOT_WORK)
                {   //再チェック(ウエイト中にスレッドが既に起動されていた場合)
                    ThreadStart ThSt = new ThreadStart(this.ThreadRun);
                    Thread t = new Thread(ThSt);
                    t.Start();
                }
                else
                {   // 結局起動しなければ　ロックは自分で解除する
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadStart", " m_csThreadTransitionLock.Release()");
                    m_csThreadTransitionLock.Release();
                }
            }
            else
            {
              HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadStart", " thread is now working!");
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>スレッド処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> スレッド起動時に呼ばれる </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual void ThreadRun()
        {
            // PT-003 言語切り替え不具合修正　地域情報をTheadにセット
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CurrentCulture;

            m_bThreadStatus = THREAD_AT_WORK; // スレッド動作中 真っ先にスレッド動作中を上げる

            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadRun", "** start **");
            HySEventObject csEvent; // イベント
            long lEventNo; // イベント番号

            
            //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadRun", " m_csThreadTransitionLock.Release()");
            m_csThreadTransitionLock.Release(); // スレッド動作移行解除
            
            for (; ; )
            {// ∞ループ
                csEvent = (HySEventObject)m_csQueue.PullObject();  // イベント待ち
                lEventNo = csEvent.GetEventNo();

                if (lEventNo == HySEventObject.CMND_STOP_SIMULATION)
                {   // シミュレーション終了の場合
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadRun", "EnveNo=CMND_STOP_SIMULAION");
                    m_csSimulator.TerminateCalculation();
                    break;
                }
                else if (lEventNo == HySEventObject.CMND_INITIALIZE_SIMULATION)
                {   // シミュレーション初期化の場合
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadRun", "EnveNo=CMND_INITIALIZE_SIMULATION");
                    HySSimulationDataContainer csContainer = m_csSimulator.GetContainer() as HySSimulationDataContainer;
                    // 時刻設定
                    m_csSimulator.SetSimuStartTime(csContainer.GetStartTime());
                    m_csSimulator.SetSimuGoalTime(csContainer.GetGoalTime());
                    m_csSimulator.SetSimuTime(csContainer.GetSimuTime());
                    m_csSimulator.SetSimuDeltaTime(csContainer.GetDeltaTime());

                    // 初期化開始
                    m_csSimulator.CmdInitializeSimulation(csEvent);
                }
                else if (lEventNo == HySEventObject.CMND_START_SIMULATION)
                {   // シミュレーション開始の場合
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadRun", "EnveNo=CMND_START_SIMULATION");
                    HySSimulationDataContainer csContainer = m_csSimulator.GetContainer() as HySSimulationDataContainer;
                    // 時刻設定
                    m_csSimulator.SetSimuStartTime(csContainer.GetStartTime());
                    m_csSimulator.SetSimuGoalTime(csContainer.GetGoalTime());
                    m_csSimulator.SetSimuTime(csContainer.GetSimuTime());
                    m_csSimulator.SetSimuDeltaTime(csContainer.GetDeltaTime());
                    // 計算開始
                    if (m_csSimulator.CmdStartSimulation(csEvent) == false)
                    {   // 開始できなければループを抜ける
                        break;
                    }
                }
                else if (lEventNo == HySEventObject.CMND_RESTART_SIMULATION)
                {   // シミュレーション再開の場合
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadRun", "EnveNo=CMND_RESTART_SIMULATION");
                    m_csSimulator.CmdRestartSimulation(csEvent);
                }
                //for (; ; )
                //{  // 無限ループ　＜－－この無限ループは　Simulator 内部で行われるべき内容
                //}
                //if (m_lStatus == SIMULATION_STOP)
                //{   // 終了中ならば
                //    break;
                //}
            }
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadRun", "** end **");

            m_bThreadStatus = THREAD_NOT_WORK; // スレッド動作せず　一番最後にスレッド終了を立てる
            GC.Collect();
        }
        /// <summary><para>method outline:</para>
        /// <para>スレッドを終了させる</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ThreadStop() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual void ThreadStop()
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadStop", "start");
            if (m_bThreadStatus == THREAD_AT_WORK)
            {   // スレッドが動作していれば
                HySEventObject csStopEvent = new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_STOP_SIMULATION);

                //m_csSimulator.CmdStopSimulation(csStopEvent); // 演算中のシミュレーターに強制終了

                m_csQueue.PushObject(csStopEvent); // 演算を終了させる

                System.Threading.Thread.Sleep(0);   // スレッドの隙間を空けるため

                //m_csSimulator.CmdPauseSimulation();
            } 

            // スレッド終了を見張る <-- 此処で見張ってはダメ（計算スレッド内で ThreadStopが呼ばれる
            /*
            for (int iLp = 0; iLp < 1000; iLp++)
            {
                if (m_lThreadStatus == THREAD_NOT_WORK)
                {
                    break;
                }
                else
                {
                    System.Threading.Thread.Sleep(300); // 300mSec Sleep
                }
            }
             */
        }
        
        /// <summary><para>method outline:</para>
        /// <para>スレッドを終了の見張り</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ThreadStopWatchDog()
        /// </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual void ThreadStopWatchDog()
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySSimThreadController::ThreadStopWatchDog", "start");
            if (m_bThreadStatus == THREAD_AT_WORK)
            {   // スレッドが動作していれば
                //HySEventObject csStopEvent = new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_STOP_SIMULATION);
                //m_csQueue.PushObject(csStopEvent); // 演算を終了させる
                for (int iLp = 0; iLp < 1000; iLp++)
                {
                    if (m_bThreadStatus == THREAD_NOT_WORK)
                    {
                        break;
                    }
                    else
                    {
                        System.Threading.Thread.Sleep(300); // 300mSec Sleep
                    }
                }
            } // end of if(m_lThreadStatus)
        }

        /// <summary><para>method outline:</para>
        /// <para>送信する補足メッセージを設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetSuppMessage( csMssage ) </para>
        /// </example>
        /// <param name="csMssage">補足メッセージ内容</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void SetSuppMessage(HySString csMssage)
        {
            m_csSndMessage.SetString(csMssage);
        }

    } // end of class
} // end of namespace
