OSDN Git Service

TriStateEvent クラスを修正。
authorくまかみ工房 <kumakamikoubou@gmail.com>
Mon, 21 Nov 2016 06:59:28 +0000 (15:59 +0900)
committerくまかみ工房 <kumakamikoubou@gmail.com>
Mon, 21 Nov 2016 06:59:28 +0000 (15:59 +0900)
使ってないけど。

FDK24/メディア/動画.cs
FDK24/同期/TriStateEvent.cs
StrokeStyleT/ステージ/演奏/スクロール譜面.cs

index e3c36f0..b305bdf 100644 (file)
@@ -52,7 +52,7 @@ namespace FDK.メディア
                        this.ループ再生する = ループ再生する;
 
                        // タスクを起動する。
-                       this.デコードタスク.Value = System.Threading.Tasks.Task.Factory.StartNew( this._デコードタスクエントリ, (object) 開始位置sec );
+                       this.デコードタスク = System.Threading.Tasks.Task.Factory.StartNew( this._デコードタスクエントリ, (object) 開始位置sec );
                        this.デコードタスク起動完了.WaitOne();
                }
 
@@ -71,7 +71,7 @@ namespace FDK.メディア
                {
                        #region " 条件チェック。"
                        //----------------
-                       if( null == this.デコードタスク.Value || // 再生をまだ開始していないか、あるいはすでに再生を完了してデコードタスクを終了済みである。
+                       if( null == this.デコードタスク ||       // 再生をまだ開始していないか、あるいはすでに再生を完了してデコードタスクを終了済みである。
                                null == this.SourceReaderEx ||          // 動画の準備に失敗した。
                                null == this.MediaType ||                       // 同上
                                null == this.WicBitmap )                        // 同上
@@ -139,7 +139,7 @@ namespace FDK.メディア
                }
                protected ConcurrentQueue<FrameQueueItem> フレームキュー = null;
                protected bool ループ再生する = false;
-               protected FDK.同期.RWLock<System.Threading.Tasks.Task> デコードタスク = new 同期.RWLock<System.Threading.Tasks.Task>();
+               protected System.Threading.Tasks.Task デコードタスク = null;
                protected System.Threading.AutoResetEvent デコードタスク起動完了 = null;
                protected System.Threading.ManualResetEvent キューが空いた = null;
                protected System.Threading.AutoResetEvent デコードタスクを終了せよ = null;
@@ -151,7 +151,7 @@ namespace FDK.メディア
 
                protected override void On活性化( デバイスリソース dr )
                {
-                       this.デコードタスク.Value = null;  // タスクが起動していないときは null であることを保証する。
+                       this.デコードタスク = null;  // タスクが起動していないときは null であることを保証する。
                        this.デコードタスク起動完了 = new System.Threading.AutoResetEvent( false );
                        this.キューが空いた = new System.Threading.ManualResetEvent( true );
                        this.デコードタスクを終了せよ = new System.Threading.AutoResetEvent( false );
@@ -342,8 +342,11 @@ namespace FDK.メディア
                        #region " デコードタスクが起動していたら、終了する。"
                        //----------------
                        this.デコードタスクを終了せよ.Set();
-                       this.デコードタスク.Value?.Wait( 2000 );
-                       this.デコードタスク.Value = null;
+
+                       if( !this.デコードタスク.Wait( 2000 ) )
+                               FDK.Log.WARNING( "デコードタスクの終了待ちがタイムアウトしました。" );
+
+                       this.デコードタスク = null;
                        //----------------
                        #endregion
 
@@ -425,6 +428,7 @@ namespace FDK.メディア
                        events[ EVID_デコードタスクを終了せよ ] = this.デコードタスクを終了せよ;
 
                        this.デコードタスク起動完了.Set();
+
                        this._再生タイマ.Value.リセットする( FDK.カウンタ.QPCTimer.秒をカウントに変換して返す( 再生開始位置sec ) );
 
                        while( System.Threading.WaitHandle.WaitAny( events ) == EVID_キューが空いた )
@@ -444,7 +448,8 @@ namespace FDK.メディア
                                }
                        }
 
-                       this.デコードタスク.Value = null;
+                       this.デコードタスク = null;
+
                        FDK.Log.Info( "デコードタスクを終了しました。" );
                }
 
index 7c1582f..3a2477f 100644 (file)
@@ -2,8 +2,7 @@
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Threading;
 
 namespace FDK.同期
 {
@@ -11,13 +10,14 @@ namespace FDK.同期
        ///             ON, OFF, 無効 の3状態を持つイベント。
        /// </summary>
        /// <remarks>
-       ///             状態が 無効 にされると、ON待ち/OFF待ちスレッドのブロックは解除され、また、それ以降状態を変更することはできなくなる。
+       ///             状態が 無効 にされると、ON待ち/OFF待ちスレッドのブロックはいずれも解除され、
+       ///             またそれ以降、状態を変更することはできなくなる(リセットすると戻る)。
        /// </remarks>
        public class TriStateEvent
        {
                public enum 状態種別 { ON, OFF, 無効 }
 
-               public 状態種別 状態
+               public ç\8a¶æ\85\8b種å\88¥ ç\8f¾å\9c¨ã\81®ç\8a¶æ\85\8b
                {
                        get
                        {
@@ -30,27 +30,29 @@ namespace FDK.同期
                        {
                                lock( this._スレッド間同期 )
                                {
+                                       if( this._状態 == 状態種別.無効 )
+                                               return;     // 一度無効になったら、以降は変更不可。
+
                                        this._状態 = value;
 
-                                       switch( this._状態 )
+                                       switch( value )
                                        {
                                                case 状態種別.ON:
-                                                       this.無効イベント.Reset();
-                                                       this.OFFイベント.Reset();
-                                                       this.ONイベント.Set();
+                                                       this._無効イベント?.Reset();
+                                                       this._OFFイベント?.Reset();
+                                                       this._ONイベント?.Set();
                                                        break;
 
                                                case 状態種別.OFF:
-                                                       this.無効イベント.Reset();
-                                                       this.ONイベント.Reset();
-                                                       this.OFFイベント.Set();
+                                                       this._無効イベント?.Reset();
+                                                       this._ONイベント?.Reset();
+                                                       this._OFFイベント?.Set();
                                                        break;
 
-                                               default:    // 無効
-                                                       this._状態 = 状態種別.無効;   // 変更不可
-                                                       this.ONイベント.Set();
-                                                       this.OFFイベント.Set();
-                                                       this.無効イベント.Set();
+                                               case 状態種別.無効:
+                                                       this._ONイベント?.Set();
+                                                       this._OFFイベント?.Set();
+                                                       this._無効イベント?.Set();
                                                        break;
                                        }
                                }
@@ -59,7 +61,7 @@ namespace FDK.同期
 
                public TriStateEvent( 状態種別 初期状態 = 状態種別.OFF )
                {
-                       this.状態 = 初期状態;
+                       this.リセットする( 初期状態 );
                }
 
                /// <summary>
@@ -70,19 +72,8 @@ namespace FDK.同期
                ///     </returns>
                public 状態種別 ONになるまでブロックする()
                {
-                       if( 状態種別.無効 == this.状態 ||
-                               状態種別.ON == this.状態 )
-                       {
-                               return this.状態;
-                       }
-
-                       // 上の if から 下の WaitOne までの間に ON になった場合に備えて、定期的に状態をチェックする。
-                       while( false == this.ONイベント.WaitOne( 100 ) )
-                       {
-                               if( 状態種別.ON == this.状態 )
-                                       break;
-                       }
-                       return this.状態;
+                       int h = EventWaitHandle.WaitAny( new EventWaitHandle[] { this._ONイベント, this._無効イベント } );
+                       return ( h == 0 ) ? 状態種別.ON : 状態種別.無効;
                }
                
                /// <summary>
@@ -93,19 +84,8 @@ namespace FDK.同期
                ///     </returns>
                public 状態種別 OFFになるまでブロックする()
                {
-                       if( 状態種別.無効 == this.状態 ||
-                               状態種別.OFF == this.状態 )
-                       {
-                               return this.状態;
-                       }
-
-                       // 上の if から 下の WaitOne までの間に OFF になった場合に備えて、定期的に状態をチェックする。
-                       while( false == this.OFFイベント.WaitOne( 100 ) )
-                       {
-                               if( 状態種別.OFF == this.状態 )
-                                       break;
-                       }
-                       return this.状態;
+                       int h = EventWaitHandle.WaitAny( new EventWaitHandle[] { this._OFFイベント, this._無効イベント } );
+                       return ( h == 0 ) ? 状態種別.OFF : 状態種別.無効;
                }
 
                /// <summary>
@@ -113,22 +93,29 @@ namespace FDK.同期
                /// </summary>
                public void 無効になるまでブロックする()
                {
-                       if( 状態種別.無効 == this.状態 )
-                               return;
+                       this._無効イベント.WaitOne();
+               }
 
-                       // 上の if から 下の WaitOne までの間に無効になった場合に備えて、定期的に状態をチェックする。
-                       while( false == this.無効イベント.WaitOne( 100 ) )
+               /// <summary>
+               ///             状態をリセットする。
+               ///             すでに無効になった後でも可。
+               /// </summary>
+               public void リセットする( 状態種別 初期状態 = 状態種別.OFF )
+               {
+                       lock( this._スレッド間同期 )
                        {
-                               if( 状態種別.無効 == this.状態 )
-                                       break;
+                               this.現在の状態 = 初期状態;
+
+                               this._無効イベント = new ManualResetEvent( false );
+                               this._ONイベント = new ManualResetEvent( 初期状態 == 状態種別.ON );
+                               this._OFFイベント = new ManualResetEvent( 初期状態 == 状態種別.OFF );
                        }
                }
 
-               protected readonly System.Threading.ManualResetEvent 無効イベント = new System.Threading.ManualResetEvent( false );
-               protected readonly System.Threading.ManualResetEvent ONイベント = new System.Threading.ManualResetEvent( false );
-               protected readonly System.Threading.ManualResetEvent OFFイベント = new System.Threading.ManualResetEvent( true );
-
                private 状態種別 _状態 = 状態種別.OFF;
+               private ManualResetEvent _無効イベント = null;
+               private ManualResetEvent _ONイベント = null;
+               private ManualResetEvent _OFFイベント = null;
                private readonly object _スレッド間同期 = new object();
        }
 }
index 118b615..5f18860 100644 (file)
@@ -68,9 +68,14 @@ namespace SST.ステージ.演奏
 
                protected override void On非活性化( デバイスリソース dr )
                {
-                       // 高頻度進行スレッドへ、終了を指示。
-                       if( null != this._高頻度進行 )
-                               this._高頻度進行.状態 = FDK.同期.TriStateEvent.状態種別.OFF;
+                       if( null != this._高頻度進行タスクへのイベント )
+                       {
+                               // 高頻度進行スレッドへ、終了を指示。
+                               this._高頻度進行タスクへのイベント.現在の状態 = FDK.同期.TriStateEvent.状態種別.OFF;
+
+                               // スレッドが終了するまで(状態が無効にされるまで)待つ必要はない。
+                               //this._高頻度進行タスクへのイベント.無効になるまでブロックする();
+                       }
                }
 
                protected override void Onデバイス依存リソースの作成( デバイスリソース dr )
@@ -215,7 +220,7 @@ namespace SST.ステージ.演奏
                };
 
                private float _画面の高さdpx = 0f;    // 進行スレッドからはデバイスリソースを参照しないので、ここにキャッシュしておく。
-               private FDK.同期.TriStateEvent _高頻度進行 = null;
+               private FDK.同期.TriStateEvent _高頻度進行タスクへのイベント = null;
                private readonly object _スレッド間同期 = new object();
 
                private void _画面内に収まるチップをすべて進行描画する( デバイスリソース dr, Action<デバイスリソース, SSTFormat.チップ, float> 描画アクション, double 現在の演奏時刻sec )
@@ -235,10 +240,11 @@ namespace SST.ステージ.演奏
                                        this.描画開始チップ番号 = 0; // -1 → 0; 演奏開始。
                                        this.チップアニメ.開始する( 最初の値: 0, 最後の値: 48, 値をひとつ増加させるのにかける時間ms: 10 );
 
+                                       this._高頻度進行タスクへのイベント = new FDK.同期.TriStateEvent( FDK.同期.TriStateEvent.状態種別.ON );
+
                                        // 高頻度進行タスクを生成。
-                                       this._高頻度進行 = new FDK.同期.TriStateEvent( FDK.同期.TriStateEvent.状態種別.ON );
                                        System.Threading.Tasks.Task.Run( () => {
-                                               _高頻度進行処理タスクエントリ();
+                                               this._高頻度進行処理タスクエントリ();
                                        } );
                                }
                                //----------------
@@ -287,7 +293,7 @@ namespace SST.ステージ.演奏
                {
                        FDK.Log.Info( $"{FDK.Utilities.現在のメソッド名} --> 開始" );
 
-                       while( this._高頻度進行.状態 == FDK.同期.TriStateEvent.状態種別.ON )
+                       while( this._高頻度進行タスクへのイベント.現在の状態 == FDK.同期.TriStateEvent.状態種別.ON )
                        {
                                lock( this._スレッド間同期 )
                                {
@@ -322,6 +328,8 @@ namespace SST.ステージ.演奏
                                System.Threading.Thread.Sleep( 1 );
                        }
 
+                       this._高頻度進行タスクへのイベント.現在の状態 = FDK.同期.TriStateEvent.状態種別.無効;
+
                        FDK.Log.Info( $"{FDK.Utilities.現在のメソッド名} <-- 終了" );
                }