InvalidOperationException
자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다.
------------------------------------------------------------------------------------------------------------------
[ 1. 발생원인 ]
- 여러 Thread 에서 하나의 컨트롤에 접근하는 경우
- Main Thread 가 관리하고 있는 Object 에 다른 Thread 가 접근하는 경우 (Main Thread 는 접근 가능, 다른 Thread 는 접근 불가능)
[ 2. 현상확인 ]
- MainForm 에 Label 과 Button 이 있음
- Label (uiLab_Value) 의 초기값 = 0
- Button (Thread Start) 에 클릭 이벤트 연동
- Thread 객체 t
* 프로그램 실행화면
* Button (Thread Start) 클릭 이벤트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 |
private void UiBtn_ThreadStart_Click(object sender, EventArgs e)
{
// Thread 가 실행중이면, 종료
if (t != null && t.IsAlive == true)
{
t.Abort();
t.Join();
t = null;
}
// Thread 생성 및 Thread 가 실행할 함수(UpNumber) 연동
t = new Thread(new ThreadStart(UpNumber));
// Thread 시작
t.Start();
} |
cs |
* Thread 가 실행할 UpNumber( ) 메서드
1
2
3
4
5
6
7
8
9 |
private void UpNumber()
{
while (true)
{
// 현재 값을 증가시킴
int nextVal = Convert.ToInt32(this.uiLab_Value.Text) + 1;
this.uiLab_Value.Text = nextVal.ToString();
}
} |
cs |
* Button (Thread Start) 을 누르면,
아래와 같이 Thread 가 실행한 UpNumber( ) 메서드 내에서 크로스 스레드 예외가 발생
[ 3. 해결방법 ]
- 다른 Thread 에서 접근하려는 Object 에 Invoke 를 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 |
private void UpNumber()
{
while (true)
{
// 현재 값을 증가시킴
int nextVal = Convert.ToInt32(this.uiLab_Value.Text) + 1;
//this.uiLab_Value.Text = nextVal.ToString();
// Invoke 를 이용하여 해당 Object 에 대한 접근 권한을 얻기
// uiLab_Value 객체에 접근하기위해 Invoke 가 요구된다면
if (this.uiLab_Value.InvokeRequired == true)
{
this.uiLab_Value.Invoke((MethodInvoker)delegate
{
this.uiLab_Value.Text = nextVal.ToString();
});
}
else
{
this.uiLab_Value.Text = nextVal.ToString();
}
}
} |
cs |
[ 4. 실행결과 ]
* 다른 Thread 가 실행 중에, 해당 화면이 종료될 경우 예외처리 필수
1
2
3
4
5
6
7
8
9
10
11 |
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
// 스레드가 살아있으면 (동작하고 있는 중이면)
if (t != null && t.IsAlive == true)
{
// 스레드 중지
t.Abort();
t.Join();
t = null;
}
} |
cs |
------------------------------------------------------------------------------------------------------------------
[ 요약 ]
- 크로스 스레드 예외가 발생하면, Invoke 를 사용하여 해결!!