using System; using System.Collections.Generic; using System.Diagnostics; namespace FDK { public class Log { /// /// これを設定しておくと、スレッドID の横に (名前) と出力されるようになる。 /// public static void 現在のスレッドに名前をつける( string 名前 ) { lock( Log.排他 ) { var ID = Log.GetCurrentThreadId(); if( Log.IDto名前.ContainsKey( ID ) ) Log.IDto名前.Remove( ID ); Log.IDto名前.Add( ID, 名前 ); } } public static void Info( string 出力 ) { lock( Log.排他 ) { Log.一定時間が経過していたら区切り線を表示する(); Trace.TraceInformation( $"{Log.日時とスレッドID}{Log.インデックスを返す( Log.深さ )}{出力}" ); } } public static void ERROR( string 出力 ) { lock( Log.排他 ) { Log.一定時間が経過していたら区切り線を表示する(); Trace.TraceError( $"{Log.日時とスレッドID} {出力}" ); } } public static void WARNING( string 出力 ) { lock( Log.排他 ) { Log.一定時間が経過していたら区切り線を表示する(); Trace.TraceWarning( $"{Log.日時とスレッドID} {出力}" ); } } public static void BeginInfo( string 開始ブロック名 ) { lock( Log.排他 ) { Log.一定時間が経過していたら区切り線を表示する(); Trace.TraceInformation( $"{Log.日時とスレッドID}{Log.インデックスを返す( Log.深さ )}{開始ブロック名} --> 開始" ); Log.深さ += 4; } } public static void EndInfo( string 終了ブロック名 ) { lock( Log.排他 ) { Log.深さ = Math.Max( ( Log.深さ - 4 ), 0 ); Log.一定時間が経過していたら区切り線を表示する(); Trace.TraceInformation( $"{Log.日時とスレッドID}{Log.インデックスを返す( Log.深さ )}{終了ブロック名} <-- 終了" ); } } /// /// 連続して呼び出しても、前回の同一識別キーでの表示から一定時間が経たないと表示しないInfoメソッド。 /// /// /// 毎秒60回の進行描画の進捗など、連続して呼び出すと膨大な数のログが出力されてしまう場合に使用する。 /// /// /// public static void 定間隔Info( string 識別キー, string 出力, double 間隔sec = 0.25 ) { lock( Log.排他 ) { if( Log.識別キー別最終表示時刻.ContainsKey( 識別キー ) ) { if( ( DateTime.Now - Log.識別キー別最終表示時刻[ 識別キー ] ).TotalSeconds >= 間隔sec ) { Log.識別キー別最終表示時刻[ 識別キー ] = DateTime.Now; Trace.TraceInformation( $"{Log.日時とスレッドID} {出力}" ); } } else { Log.識別キー別最終表示時刻.Add( 識別キー, DateTime.Now ); Trace.TraceInformation( $"{Log.日時とスレッドID} {出力}" ); } } } private static string 日時とスレッドID { get { var NETスレッドID = System.Threading.Thread.CurrentThread.ManagedThreadId; var Win32スレッドID = Log.GetCurrentThreadId(); var スレッド識別文字列 = ( Log.IDto名前.ContainsKey( Win32スレッドID ) ) ? $"({Log.IDto名前[ Win32スレッドID ]})" : ""; return $"{DateTime.Now.ToLongTimeString()} [{NETスレッドID:00},0x{Win32スレッドID:x}{スレッド識別文字列}]"; } } private static readonly Dictionary IDto名前 = new Dictionary(); private static Dictionary 識別キー別最終表示時刻 = new Dictionary(); private static TimeSpan 経過時間 { get { var 現在時刻 = DateTime.Now; var 経過時間 = 現在時刻 - Log.最終表示時刻; Log.最終表示時刻 = 現在時刻; // 更新 return 経過時間; } } private static DateTime 最終表示時刻 = DateTime.Now; private const double 最小区切り時間 = 2.0; // 区切り線を入れる最小の間隔[秒]。 private static int 深さ = 0; private static readonly object 排他 = new object(); private static void 一定時間が経過していたら区切り線を表示する() { if( Log.最小区切り時間 < Log.経過時間.TotalSeconds ) Trace.TraceInformation( "・・・" ); } private static string インデックスを返す( int 長さ ) { string index = " "; int len = 長さ * 2; while( 0 < len ) { index += " ".Substring( 0, Math.Min( len, 10 ) ); len -= 10; } return index; } #region " Win32 API " //----------------- [System.Runtime.InteropServices.DllImport( "kernel32.dll" )] private static extern uint GetCurrentThreadId(); //----------------- #endregion } }