1. 에러 발생
System.InvalidOperationException: 크로스 스레드 작업이 잘못되었습니다. 'label_Connection' 컨트롤이 자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다.
위치: System.Windows.Forms.Control.get_Handle()
위치: System.Windows.Forms.Control.set_WindowText(String value)
위치: System.Windows.Forms.Control.set_Text(String value)
2. 원인 분석
- 멀티 쓰레드 환경에서 Winform 컨트롤을 다른 스레드에서 접근할 때 발생
- 현재 Thread에서 실시간으로 UI를 변경하는 부분이 존재
//4. Simulation Thread 실행
SimCore.worker = new Thread(UpdateDataGrid);
SimCore.worker.IsBackground = true;
SimCore.worker.Start();
UpdateDataGrid() 쓰레드 내에서 UI를 변경하는 경우 발생
--> label_Connection.Text = string.Format("Connected ({0})", connection_count);
3. 해결 방법
- InvokeRequired : 호출자가 컨트롤이 만들어진 스레드(메인스레드)와 다른 스레드에 있기 때문에 메서드를 통해 호출해야하는지 판단 (True 인 경우 충돌 발생)
- Invoke : 컨트롤을 생성한 스레드에서 동기식으로 실행 (메인 쓰레드에게 함수 호출을 위임)
- BeginInvoke : 비동기식으로 실행
private void UpdateDataGrid()
{
ConfigManager.log.Info("Form_Main.UpdateDataGrid() - Thread UpdateDataGrid() Start.");
int connection_count = 0;
while (true)
{
try
{
//......다른 Logic
if(label_Connection.InvokeRequired)
{
label_Connection.BeginInvoke(new Action(() => label_Connection.Text = string.Format("Connected ({0})", connection_count)));
connection_count = SimCore.IedServer.GetNumberOfOpenConnections();
}
else
{
label_Connection.Text = string.Format("Connected ({0})", connection_count);
}
string msg = string.Format("Current Connection Count = {0}", connection_count);
ConfigManager.log.Debug(msg);
}
}
//...
}
}
'#1프로그래밍 > #5 C#' 카테고리의 다른 글
[C#, Button, Image] C# 버튼에 이미지 넣기 (0) | 2022.11.14 |
---|---|
[C#] DLL 'xxxxx' 을(를) 로드할 수 없습니다. (HRESULT: 0x8007007E) (0) | 2022.11.09 |
[C#, VisualStudio] log4net 적용하기 (0) | 2022.10.07 |