Thread - 크로스 스레드 (Cross Thread) 해결 방법 2가지
C#에서 여러개의 Form을 왔다갔다 하면서 다양한 컨트롤을 제어하다보면 심심치 않게 아래와 같은 크로스 스레드 작업 관련 오류 문구를 확인할 수 있다.
이는 해당 컨트롤을 관리하는 스레드가 아닌 다른 스레드에서 해당 컨트롤에 접근하게 되면 크로스 스레드 오류가 발생한다고 한다.
1. CheckForIllegalCrossThreadCalls
크로스 스레드 해결 방법으로 첫번째는
CheckForIllegalCrossThreadCalls의 속성값을 False로 바꾸는 것이다.
CheckForIllegalCrossThreadCalls = false;
이는 크로스 스레드를 무시하겠다는 설정으로 쓰레드 충돌을 방지하는 것이 아닌
쓰레드가 충돌하여도 예외 처리를 무시하겠다는 설정이다. 따라서 권장하는 바는 아니다.
2. InvokeRequired + invoke
따라서 권장하는 부분은 아래와 같이 InvokeRequired 속성과 Invoke 매서드를 혼합해서 사용하는 방법이다.
먼저 InvokeRequired 속성이 True인 경우 해당 컨트롤을 접근하는 스레드가 기존 호출하는 스레드와 다른경우이다.
따라서 Cross Thread가 발생할 수 있는 경우에 해당한다.
InvokeRequired를 통해 CrossThread가 발생하는 상황을 분리했다면 Invoke 매서드를 통해
대리자를 이용해서 메인 스레드에 있는 컨트롤에 접근해서 크로스 스레드의 오류를 방지해준다.
if (this.InvokeRequired) // 참인경우 Cross Thread가 발생하는 경우
{
this.Invoke(new Action(delegate ()
{
//크로스 스레드가 생성되는 코드부
}));
}
else{}
여기서 Invoke 매서드의 인자로 Action을 사용하는 경우와 MethodInvoker를 사용하는 경우 2가지로 나뉜다.
아래의 설명에도 나왔지만 Action은 매개변수를 사용하지 않은 매서드를 실행할 경우 사용되고
(--> Action은 최대 16개의 인자를 가지고 반환값을 가지지 않는 경우)
(--> Func는 최대 16개의 인자를 가지고 반환값도 가지는 경우)
MethodInvoker는 매개변수를 사용하는 메서드를 실행할 경우 사용되는 듯 싶다.
※ 하지만 인자가 없는 메서드나 함수를 직접 입력했을때 두가지 모두 사용해도 되는 경우가 있다. 그리고 Action은 System에 정의되어 있고 MethodInvoker는 System.Windows.Forms에 정의되어 있는것으로 봤을때 Action이 좀 더 호환성이 좋을 것 같다. 오로지 지극히 개인적인 생각이므로 이부분에 대해선 조금 더 공부해볼 필요가 있다.
여기서 말하는 매개변수를 사용한다는 거는 반환값이 있다는 얘기라고 생각하면 되는건가?? 인자는 두가지 케이스다 사용하는것으로 알고있는데..
이상하게 Microsoft 문서의 MethodInvoker에 대한 설명을 보면 또 다른 설명이 적혀있음을 알 수 있다. (뭐가 맞는 것일까)
추가로 Action의 경우 Action <T, T, T, ~> 이런식으로 사용하면 최대 16개 까지의 매개변수를 가지는 메서드를 대리자로 실행 할 수 있다.
댓글