본문 바로가기
C++ 200제/코딩 IT 정보

C# Invoke로 크로스 스레드 해결, 간략한 소스 응용 [C#강좌]

by vicddory 2017. 11. 18.

C# Invoke로 크로스 스레드 해결, 간략한 소스 응용 [C#강좌]


C# Invoke는 이럴 때 써야 합니다. 아래 에러 메시지 보시죠.


InvalidOperationException이(가) 처리되지 않았습니다.


또는, 이럴 때도 C# Invoke를 써야 하죠.


처리되지 않은 'System.InvalidOperationException' 형식의 예외가 System.Windows.Forms.dll에서 발생했습니다.


추가 정보: 크로스 스레드 작업이 잘못되었습니다. 'tb_received' 컨트롤이 자신이 만들어진 스레드가 아닌 스레드에서 액세스 되었습니다.


InvalidOperationException이 처리되지 않았습니다C# Invoke로 크로스 스레드 해결, 간소화된 소스 응용 [C#강좌]


위 에러가 발생했을 때 해결하는 방법은 3가지였습니다. (C# Invoke를 사용하지 않았을 때)


1. 델리게이트를 선언하고 그곳에 맞는 콜백 함수를 선언하여 처리.

2. 스레드 내부에 if else를 선언하여 예외 처리 같지 않은 예외 처리.

3. 백그라운드 워커로 처리.

3번 방법은 안정성 면에서 좋지 않고,

2번 방법도 마찬가지고,

1번 방법이 가장 괜찮으나 소스가 길어져 불만이었습니다.


UI가 복잡해지면 소스가 너무 많아져 배보다 배꼽이 더 커지는 상황도 종종 발생합니다. 그렇지만, MS 측에서도 개발자를 위한 축약 소스의 양을 늘리고 있습니다. 크로스 스레드 작업을 해결하려는 축약된 소스도 작년인가 재작년부터 제공하고 있죠.


그래서 이제는 길게 소스를 꾸미거나, 여기저기 분산시켜 작성할 필요가 없습니다. 아래처럼 간단하게 해결할 수 있어요. 바로 아래는 텍스트 박스의 Text를 교체하는 소스입니다.


딱 봐도 엄청 간단해 보입니다.


1
2
3
tb_received.Invoke((MethodInvoker) delegate () {
    tb_received.AppendText(Environment.NewLine + "msg");
});
cs


텍스트 박스의 속성 중 C# Invoke를 직접 호출하여 축약된 형태로 소스를 꾸밀 수 있어요.


AppendText() 함수는 그동안 크로스 스레드 작업에서 벗어나지 못했습니다. 그건 4.5 이상에서도 마찬가지지만, 축약된 형태로 간략화할 수 있습니다.


아래는 또 다른 예제로 리스트 박스의 인덱스를 알아내거나 Item 속성 중 하나를 삭제하는 소스입니다.


1
2
3
4
5
6
7
8
lstbox_.Invoke((MethodInvoker)delegate ()
{
    dictionary_lst_.Remove("some_index");
 
    int idx = lstbox_.Items.IndexOf("some text2");
 
    lstbox_.Items.Remove("some text3");
});
cs


소스가 간략하다 보니 그 안에서 다룰 수 있는 것들도 늘어났습니다.


특정 아이템의 인덱스를 알아내어 없애거나, C# Invoke 함수 내부에서 딕셔너리로 접근하여 원하는 항목도 삭제할 수 있습니다.


이제는 스레드 내부를 오버라이드하거나, 델리게이트와 콜백 함수를 별도로 선언할 필요가 없습니다. 축약된 형태의 소스로 간단히 크로스 스레드 작업을 처리할 수 있습니다. 더 편리해지고 소스가 짧아지게 되었습니다. 좋아졌네요.


ps. 구현 예제


InvalidOperationException이 처리되지 않았습니다C# Invoke로 크로스 스레드 해결, 간략한 소스 응용 [C#강좌]


위는 리스트 박스의 요소를 삭제하거나 추가하는 함수입니다. 중간에 C# Invoke를 호출하여 간단하게 크로스 스레드 문제를 해결하고 있죠. 이제는 긴 소스를 구현하지 않아도 됩니다.


관련 기능을 한 함수로 모아 처리할 수 있어요.


C# Invoke로 크로스 스레드 해결, 간략한 소스 응용 [C#강좌]

댓글