'#크로스스레드'에 해당되는 글 1건

  1. 2019.07.07 [C#] 자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다 2

 

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();
                = 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();
                = null;
            }
        }
cs

 

 

------------------------------------------------------------------------------------------------------------------

 

[ 요약 ]

- 크로스 스레드 예외가 발생하면, Invoke 를 사용하여 해결!!

Posted by 오늘은 휴가
,