/// <summary> /// /// </summary> /// <param name="iMemberInfoHandler"></param> /// <param name="iBeforeEnqueueMemberInfo"></param> /// <param name="iTaskException"></param> public static void Register(Func <MemberInformation, bool> iMemberInfoHandler, Func <MemberInformation, bool> iBeforeEnqueueMemberInfo = null, EventHandler <UnobservedTaskExceptionEventArgs> iTaskException = null) { LibraryInformation.Initialize(); ThreadLocalInformation.Initialize(); if (_loopRecord.zzIsNotNull()) { _loopRecord.Stop(); //TODO: Wait. } if (iMemberInfoHandler.zzIsNull()) { throw new ArgumentNullException(nameof(iMemberInfoHandler), "iMemberInfoHandler.zzIsNull()"); } ThreadLocalMemberObserver.MemberInfoHandler = iMemberInfoHandler; if (iBeforeEnqueueMemberInfo.zzIsNotNull()) { ThreadLocalMemberObserver.BeforeEnqueueMemberInfo = iBeforeEnqueueMemberInfo; } TaskScheduler.UnobservedTaskException += (iTaskException.zzIsNull() ? ThreadLocalMemberObserver.UnobservedTaskException : iTaskException); _loopRecord = LoopObserver.SpinUntilInBackground(memberInfoHandler, TaskCreationOptions.LongRunning); //TODO: Test self. }
/// <summary> /// /// </summary> /// <param name="iStatus"></param> /// <param name="iCallerMemberName"></param> /// <param name="iCallerFilePath"></param> /// <param name="iCallerLineNumber"></param> public MemberInformation(EMemberStatus iStatus, [CallerMemberName] string iCallerMemberName = ConstString.Empty, [CallerFilePath] string iCallerFilePath = ConstString.Empty, [CallerLineNumber] int iCallerLineNumber = ConstNumberValue.Zero) { if (iStatus == EMemberStatus.Unknown) { throw new ArgumentException("iStatus == EMemberStatus.Unknown"); } else if (iStatus == EMemberStatus.HasException) { throw new ArgumentException("iStatus == EMemberStatus.HasException"); } _creationTime = TimeHelper.GetTimeNowByPreprocessor(); Status = iStatus; Name = iCallerMemberName; FilePath = iCallerFilePath; LineNumber = iCallerLineNumber; UniqueThreadID = ThreadLocalInformation.GetUniqueID(); UniqueMemberID = (UniqueThreadID ^ Name.GetHashCode() ^ FilePath.GetHashCode()); Exception = null; ExceptionStackTrace = ConstString.Empty; }
/// <summary> /// /// </summary> /// <returns></returns> public static bool CheckSeedValuesNoDuplicate() { for (int i = ConstValue.StartIndex; i < ThreadLocalInformation.GetUniqueIDValues().zzGetLastIndex(); ++i) { for (int j = (i + ConstNumberValue.One); j < ThreadLocalInformation.GetUniqueIDValues().Count; ++j) { if (j == i) { return(false); } } } return(true); }
/// <summary> /// /// </summary> /// <param name="ioException"></param> /// <param name="iExceptionStackTrace"></param> /// <param name="iCallerMemberName"></param> /// <param name="iCallerFilePath"></param> /// <param name="iCallerLineNumber"></param> public MemberInformation(Exception ioException, string iExceptionStackTrace, [CallerMemberName] string iCallerMemberName = ConstString.Empty, [CallerFilePath] string iCallerFilePath = ConstString.Empty, [CallerLineNumber] int iCallerLineNumber = ConstNumberValue.Zero) { _creationTime = TimeHelper.GetTimeNowByPreprocessor(); Status = EMemberStatus.HasException; Name = iCallerMemberName; FilePath = iCallerFilePath; LineNumber = iCallerLineNumber; UniqueThreadID = ThreadLocalInformation.GetUniqueID(); UniqueMemberID = (UniqueThreadID ^ Name.GetHashCode() ^ FilePath.GetHashCode()); Exception = ioException; ExceptionStackTrace = iExceptionStackTrace; }
/// <summary> /// /// </summary> public void PrintTimeAndThreadAndValue() { const int mLoopTimes = ConstNumberValue.Five; const int mParallelCount = ConstNumberValue.Ten; //arrange bool mActual1 = false; //act CheckSeedValuesNoDuplicate(); Parallel.For(ConstValue.StartIndex, mParallelCount, i => { for (int j = ConstValue.StartIndex; j < mLoopTimes; ++j) { Debug.WriteLine(StringHelper.DefaultJoin(TimeHelper.GetTimeNowByPreprocessor().Ticks, ThreadLocalInformation.GetCreationTime().Ticks, ThreadLocalInformation.GetUniqueID(), i, j, PortableThreadSafeRandom.GetInstance().Next())); } }); mActual1 = PortableThreadSafeRandom.CheckSeedValuesNoDuplicate(); Debug.WriteLine(StringHelper.DefaultJoin(ThreadLocalInformation.GetCreationTimeValues().Count, string.Join(", ", ThreadLocalInformation.GetCreationTimeValues()))); Debug.WriteLine(StringHelper.DefaultJoin(ThreadLocalInformation.GetGuidValues().Count, string.Join(", ", ThreadLocalInformation.GetGuidValues()))); Debug.WriteLine(StringHelper.DefaultJoin(ThreadLocalInformation.GetUniqueIDValues().Count, string.Join(", ", ThreadLocalInformation.GetUniqueIDValues()))); if (!mActual1) { for (int i = ConstValue.StartIndex; i < ThreadLocalInformation.GetUniqueIDValues().zzGetLastIndex(); ++i) { for (int j = (i + ConstNumberValue.One); j < ThreadLocalInformation.GetUniqueIDValues().Count; ++j) { if (j == i) { Debug.WriteLine(StringHelper.DefaultJoin(i, j, ThreadLocalInformation.GetUniqueIDValues()[i])); } } } } //assert Contract.Assert(mActual1); }
/// <summary> /// /// </summary> public void CheckSeedValuesNoDuplicate() { const int mLoopTimes = ConstNumberValue.Twenty; const int mParallelCount = ConstNumberValue.Twenty; //arrange bool mActual1 = false; //act for (int i = ConstValue.StartIndex; i < mLoopTimes; ++i) { Parallel.For(ConstValue.StartIndex, mParallelCount, j => { PortableThreadSafeRandom.GetInstance().Next(); }); } mActual1 = PortableThreadSafeRandom.CheckSeedValuesNoDuplicate(); Debug.WriteLine(StringHelper.DefaultJoin(ThreadLocalInformation.GetCreationTimeValues().Count, string.Join(", ", ThreadLocalInformation.GetCreationTimeValues()))); Debug.WriteLine(StringHelper.DefaultJoin(ThreadLocalInformation.GetGuidValues().Count, string.Join(", ", ThreadLocalInformation.GetGuidValues()))); Debug.WriteLine(StringHelper.DefaultJoin(ThreadLocalInformation.GetUniqueIDValues().Count, string.Join(", ", ThreadLocalInformation.GetUniqueIDValues()))); if (!mActual1) { for (int i = ConstValue.StartIndex; i < ThreadLocalInformation.GetUniqueIDValues().zzGetLastIndex(); ++i) { for (int j = (i + ConstNumberValue.One); j < ThreadLocalInformation.GetUniqueIDValues().Count; ++j) { if (j == i) { Debug.WriteLine(StringHelper.DefaultJoin(i, j, ThreadLocalInformation.GetUniqueIDValues()[i])); } } } } //assert Contract.Assert(mActual1); }
internal void SetStatus(ELoopStatus iTarget) { switch (iTarget) { //case ELoopStatus.Unknown: // break; case ELoopStatus.IsWaiting: { if (ThreadLocalInformation.GetUniqueID() != UniqueThreadID) { throw new ArgumentException(StringHelper.DefaultJoin("ThreadLocalInformation.GetUniqueID() != UniqueThreadID", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } switch (GetStatus()) { //case ELoopStatus.IsWaiting: // break; case ELoopStatus.Unknown: //break; //case ELoopStatus.IsInvoking: // break; //case ELoopStatus.IsStopping: // break; case ELoopStatus.IsPausing: _status = iTarget; break; //case ELoopStatus.IsStopped: // break; default: throw new ArgumentException(StringHelper.DefaultJoin("default:", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } } break; case ELoopStatus.IsInvoking: { switch (GetStatus()) { case ELoopStatus.Unknown: //break; case ELoopStatus.IsWaiting: //break; case ELoopStatus.IsPausing: //break; case ELoopStatus.IsStopping: _status = iTarget; break; case ELoopStatus.IsInvoking: break; //case ELoopStatus.IsStopped: // break; default: throw new ArgumentException(StringHelper.DefaultJoin("default:", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } } break; case ELoopStatus.IsPausing: { if (ThreadLocalInformation.GetUniqueID() == UniqueThreadID) { throw new ArgumentException(StringHelper.DefaultJoin("ThreadLocalInformation.GetUniqueID() == UniqueThreadID", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } switch (GetStatus()) { //case ELoopStatus.Unknown: // break; case ELoopStatus.IsWaiting: //break; case ELoopStatus.IsPausing: break; case ELoopStatus.IsInvoking: //break; case ELoopStatus.IsStopping: _status = iTarget; break; //case ELoopStatus.IsStopped: // break; default: throw new ArgumentException(StringHelper.DefaultJoin("default:", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } } break; case ELoopStatus.IsStopping: { if (ThreadLocalInformation.GetUniqueID() == UniqueThreadID) { throw new ArgumentException(StringHelper.DefaultJoin("ThreadLocalInformation.GetUniqueID() == UniqueThreadID", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } switch (GetStatus()) { //case ELoopStatus.Unknown: // break; case ELoopStatus.IsWaiting: //break; case ELoopStatus.IsInvoking: //break; case ELoopStatus.IsPausing: _status = iTarget; break; case ELoopStatus.IsStopping: break; //case ELoopStatus.IsStopped: // break; default: throw new ArgumentException(StringHelper.DefaultJoin("default:", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } } break; case ELoopStatus.IsStopped: { if (ThreadLocalInformation.GetUniqueID() != UniqueThreadID) { throw new ArgumentException(StringHelper.DefaultJoin("ThreadLocalInformation.GetUniqueID() != UniqueThreadID", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } switch (GetStatus()) { //case ELoopStatus.Unknown: // break; //case ELoopStatus.IsWaiting: // break; case ELoopStatus.IsInvoking: //break; case ELoopStatus.IsPausing: //break; case ELoopStatus.IsStopping: _status = iTarget; break; //case ELoopStatus.IsStopped: // break; default: throw new ArgumentException(StringHelper.DefaultJoin("default:", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } } break; default: throw new ArgumentException(StringHelper.DefaultJoin("default:", ThreadLocalInformation.GetUniqueID(), UniqueThreadID, iTarget, GetStatus())); } }
/// <summary> /// /// </summary> public LoopRecord() { UniqueThreadID = ThreadLocalInformation.GetUniqueID(); _status = ELoopStatus.Unknown; }
static ThreadSafeRandom() { _localRandom = new ThreadLocal <Random>(() => new Random(ThreadLocalInformation.GetUniqueID()), true); }