using System.Threading;

namespace CS_sample
{
    /// <summary>
    /// ワーカースレッドクラス
    /// </summary>
    class Worker
    {
        #region メンバ変数定義
        private EventWaitHandle _crwFunctionEvent;  // イベントハンドル（CRW関数呼出し通知）

        private EventWaitHandle _exitThreadEvent;   // イベントハンドル（スレッド終了通知）


        private Thread _Thread;                     // スレッド

        private CrwFunction _crwFunction;           // 呼出し対象のCRW関数

        public string _ThreadName;
        #endregion

        #region コンストラクタ
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Worker(string ThreadName)
        {
            _crwFunctionEvent = new AutoResetEvent(false);
            _exitThreadEvent = new AutoResetEvent(false);
            _Thread = new Thread(this.ThreadRun);
            _Thread.Start();
            _ThreadName = ThreadName;
        }
        #endregion

        #region
        /// <summary>
        /// CRW関数呼出し

        /// </summary>
        /// <param name="crwFunction"></param>
        public void CallCrwFunction(CrwFunction crwFunction)
        {
            _crwFunction = crwFunction; 
            // EventWaitHandleのSetメンバは
            // イベントの状態をシグナル状態に設定し、待機している 1 つ以上のスレッドが進行できるようになる

            // シグナル状態をグリーンにする、実行することによって
            // WaitHandle.WaitAny(eventArray)を通り抜ける

            _crwFunctionEvent.Set();        

        }
        #endregion

        #region
        /// <summary>
        /// ワーカスレッド終了

        /// </summary>
        public void TerminateThread()       // ターミネートスレッド
        {
            _exitThreadEvent.Set();         // イベントを青信号
            _Thread.Join();                 // 呼び出し元のスレッドをブロック(これが終了処理?)    
        }
        #endregion

        #region
        /// <summary>
        /// ワーカスレッド本体

        /// </summary>
        private void ThreadRun()
        {
            WaitHandle[] eventArray = new WaitHandle[2] { _crwFunctionEvent, _exitThreadEvent };
            // スレッドのメインループ

            while (1 != WaitHandle.WaitAny(eventArray)) // ここで待機

            {
                // crwFunction call
                _crwFunction.Call();                    // ここで実行

            }
        }
        #endregion

        #region ワーカスレッドの名前取得

        public string GetName()
        {
            return _ThreadName;
        }
        #endregion
    }
}
