Fix: 상태머신 루프 블로킹 문제 수정 - SPS 이벤트 핸들러 비동기 처리 및 타임아웃 보호 추가
- sm_SPS 이벤트 핸들러에서 장치 연결 및 상태 전송을 비동기로 처리 - DeviceConnectionWorker 스레드로 장치 연결 분리 - SPS(1초), Running(2초) 타임아웃 보호 추가 - 상태머신 모니터링 디버그 창 추가 (fStateMachineDebug) - F11/F12 단축키로 스레드 덤프 및 디버그 브레이크 지원 - RaiseMessage 이벤트 비동기 처리로 로그 블로킹 방지
This commit is contained in:
@@ -48,6 +48,26 @@ namespace Project
|
||||
}
|
||||
else if (e1.KeyCode == Keys.F5) btAutoRun.PerformClick();
|
||||
else if (e1.KeyCode == Keys.F9) btAutoRun.PerformClick();
|
||||
else if (e1.KeyCode == Keys.F11 && System.Diagnostics.Debugger.IsAttached)
|
||||
{
|
||||
// F11: 모든 스레드 상태 덤프
|
||||
DumpAllThreadsState();
|
||||
}
|
||||
else if (e1.KeyCode == Keys.F12 && System.Diagnostics.Debugger.IsAttached)
|
||||
{
|
||||
// F12: 다음 sm_Running 호출시 디버거 중단
|
||||
RequestDebugBreak = true;
|
||||
var lastCall = DateTime.Now - lastSmRunningTime;
|
||||
PUB.log.Add("DEBUG", $"F12 pressed - 마지막 sm_Running 호출: {lastCall.TotalSeconds:F1}초 전, IsThreadRun: {PUB.sm.IsThreadRun}");
|
||||
System.Windows.Forms.MessageBox.Show(
|
||||
$"다음 sm_Running 호출시 디버거가 중단됩니다.\n\n" +
|
||||
$"마지막 호출: {lastCall.TotalSeconds:F1}초 전\n" +
|
||||
$"IsThreadRun: {PUB.sm.IsThreadRun}\n" +
|
||||
$"Current Step: {PUB.sm.Step}",
|
||||
"디버그 모드",
|
||||
System.Windows.Forms.MessageBoxButtons.OK,
|
||||
System.Windows.Forms.MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
if (DateTime.Now > PUB.LastInputTime) PUB.LastInputTime = DateTime.Now;
|
||||
};
|
||||
@@ -239,15 +259,67 @@ namespace Project
|
||||
PUB.sm.SetMsgOptOff(); //모든 메세지출력을 해제한다. (이벤트는 동작함)
|
||||
|
||||
PUB.log.Add("State Machine Start");
|
||||
PUB.sm = new StateMachine.StateMachine();
|
||||
|
||||
try
|
||||
{
|
||||
PUB.sm = new StateMachine.StateMachine();
|
||||
PUB.log.Add("StateMachine", $"객체 생성 완료 - Type: {PUB.sm.GetType().FullName}");
|
||||
|
||||
// StateMachine 객체의 속성 확인
|
||||
var smType = PUB.sm.GetType();
|
||||
var properties = smType.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
|
||||
PUB.log.Add("StateMachine", $"Public Properties: {properties.Length}개");
|
||||
|
||||
var methods = smType.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
|
||||
PUB.log.Add("StateMachine", $"Public Methods: {methods.Length}개");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PUB.log.AddE($"StateMachine 객체 생성 실패: {ex.Message}");
|
||||
PUB.log.AddE($"StackTrace: {ex.StackTrace}");
|
||||
throw;
|
||||
}
|
||||
|
||||
PUB.sm.StepChanged += sm_StepChanged;
|
||||
PUB.log.Add("StateMachine", "StepChanged 이벤트 등록 완료");
|
||||
|
||||
PUB.sm.Message += sm_Message;
|
||||
PUB.log.Add("StateMachine", "Message 이벤트 등록 완료");
|
||||
|
||||
PUB.sm.Running += sm_Running;
|
||||
PUB.log.Add("StateMachine", "Running 이벤트 등록 완료");
|
||||
|
||||
PUB.sm.SPS += sm_SPS;
|
||||
PUB.log.Add("StateMachine", "SPS 이벤트 등록 완료");
|
||||
|
||||
PUB.sm.Start();
|
||||
PUB.log.Add("StateMachine", $"Start() 호출 완료 - IsThreadRun:{PUB.sm.IsThreadRun}");
|
||||
|
||||
// 스레드 시작 대기 (최대 3초)
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
System.Threading.Thread.Sleep(100);
|
||||
if (PUB.sm.IsThreadRun)
|
||||
{
|
||||
PUB.log.Add("StateMachine", $"스레드 시작 확인됨 ({i * 100}ms 소요)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PUB.sm.IsThreadRun)
|
||||
{
|
||||
PUB.log.AddE( "경고: 3초 대기 후에도 스레드가 시작되지 않음!");
|
||||
System.Windows.Forms.MessageBox.Show(
|
||||
"상태머신 스레드가 시작되지 않았습니다.\n" +
|
||||
"로그 파일을 확인하세요.",
|
||||
"오류",
|
||||
System.Windows.Forms.MessageBoxButtons.OK,
|
||||
System.Windows.Forms.MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
tmDisplay.Tick += tmDisplay_Tick;
|
||||
tmDisplay.Start(); //start Display
|
||||
PUB.log.Add("Display", "Display Timer 시작 완료");
|
||||
|
||||
this.btDebug.Visible = System.Diagnostics.Debugger.IsAttached || PUB.setting.UseDebugMode;
|
||||
|
||||
@@ -1015,6 +1087,68 @@ namespace Project
|
||||
}
|
||||
}
|
||||
|
||||
private void DumpAllThreadsState()
|
||||
{
|
||||
try
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine("===== 스레드 상태 덤프 =====");
|
||||
sb.AppendLine($"시간: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
|
||||
sb.AppendLine($"마지막 sm_Running 호출: {(DateTime.Now - lastSmRunningTime).TotalSeconds:F1}초 전");
|
||||
sb.AppendLine($"sm_Running 호출 횟수: {sm_Running_CallCount}");
|
||||
sb.AppendLine($"IsThreadRun: {PUB.sm.IsThreadRun}");
|
||||
sb.AppendLine($"Current Step: {PUB.sm.Step}");
|
||||
sb.AppendLine($"Current RunStep: {PUB.sm.RunStep}");
|
||||
sb.AppendLine();
|
||||
|
||||
var process = System.Diagnostics.Process.GetCurrentProcess();
|
||||
sb.AppendLine($"총 스레드 수: {process.Threads.Count}");
|
||||
sb.AppendLine();
|
||||
|
||||
foreach (System.Diagnostics.ProcessThread thread in process.Threads)
|
||||
{
|
||||
sb.AppendLine($"Thread {thread.Id}:");
|
||||
sb.AppendLine($" State: {thread.ThreadState}");
|
||||
sb.AppendLine($" Priority: {thread.PriorityLevel}");
|
||||
if (thread.ThreadState == System.Diagnostics.ThreadState.Wait)
|
||||
{
|
||||
sb.AppendLine($" WaitReason: {thread.WaitReason}");
|
||||
}
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
var dump = sb.ToString();
|
||||
PUB.log.Add("THREAD_DUMP", dump);
|
||||
Console.WriteLine(dump);
|
||||
|
||||
MessageBox.Show(
|
||||
$"스레드 덤프 완료\n로그 파일에 저장되었습니다.\n\n" +
|
||||
$"마지막 sm_Running: {(DateTime.Now - lastSmRunningTime).TotalSeconds:F1}초 전\n" +
|
||||
$"IsThreadRun: {PUB.sm.IsThreadRun}",
|
||||
"스레드 덤프",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PUB.log.AddE($"DumpAllThreadsState 오류: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void stateMachineDebugToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var debugForm = new Dialog.fStateMachineDebug();
|
||||
debugForm.Show();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"디버그 창을 열 수 없습니다:\n{ex.Message}", "오류",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void editorToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user