this.ループ再生する = ループ再生する;
// タスクを起動する。
- this.デコードタスク.Value = System.Threading.Tasks.Task.Factory.StartNew( this._デコードタスクエントリ, (object) 開始位置sec );
+ this.デコードタスク = System.Threading.Tasks.Task.Factory.StartNew( this._デコードタスクエントリ, (object) 開始位置sec );
this.デコードタスク起動完了.WaitOne();
}
{
#region " 条件チェック。"
//----------------
- if( null == this.デコードタスク.Value || // 再生をまだ開始していないか、あるいはすでに再生を完了してデコードタスクを終了済みである。
+ if( null == this.デコードタスク || // 再生をまだ開始していないか、あるいはすでに再生を完了してデコードタスクを終了済みである。
null == this.SourceReaderEx || // 動画の準備に失敗した。
null == this.MediaType || // 同上
null == this.WicBitmap ) // 同上
}
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;
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 );
#region " デコードタスクが起動していたら、終了する。"
//----------------
this.デコードタスクを終了せよ.Set();
- this.デコードタスク.Value?.Wait( 2000 );
- this.デコードタスク.Value = null;
+
+ if( !this.デコードタスク.Wait( 2000 ) )
+ FDK.Log.WARNING( "デコードタスクの終了待ちがタイムアウトしました。" );
+
+ this.デコードタスク = null;
//----------------
#endregion
events[ EVID_デコードタスクを終了せよ ] = this.デコードタスクを終了せよ;
this.デコードタスク起動完了.Set();
+
this._再生タイマ.Value.リセットする( FDK.カウンタ.QPCTimer.秒をカウントに変換して返す( 再生開始位置sec ) );
while( System.Threading.WaitHandle.WaitAny( events ) == EVID_キューが空いた )
}
}
- this.デコードタスク.Value = null;
+ this.デコードタスク = null;
+
FDK.Log.Info( "デコードタスクを終了しました。" );
}
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Threading;
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
{
{
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;
}
}
public TriStateEvent( 状態種別 初期状態 = 状態種別.OFF )
{
- this.状態 = 初期状態;
+ this.リセットする( 初期状態 );
}
/// <summary>
/// </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>
/// </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>
/// </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();
}
}
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 )
};
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 )
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._高頻度進行処理タスクエントリ();
} );
}
//----------------
{
FDK.Log.Info( $"{FDK.Utilities.現在のメソッド名} --> 開始" );
- while( this._高頻度進行.状態 == FDK.同期.TriStateEvent.状態種別.ON )
+ while( this._高頻度進行タスクへのイベント.現在の状態 == FDK.同期.TriStateEvent.状態種別.ON )
{
lock( this._スレッド間同期 )
{
System.Threading.Thread.Sleep( 1 );
}
+ this._高頻度進行タスクへのイベント.現在の状態 = FDK.同期.TriStateEvent.状態種別.無効;
+
FDK.Log.Info( $"{FDK.Utilities.現在のメソッド名} <-- 終了" );
}