UI 그리고 Thread 프로그래밍하다 간혹 "크로스 스레드" 문제를 부딪치게 되면서,
Invoke 및 Control.InvokeRequired 속성을 알아보게 되었습니다.
스레드들에 대해 약간 보자면...
- Thread Affinity(스레드 선호도) : 기본적으로 그 UI 컨트롤을 생성한 쓰레드만이 해당 UI객체를 접속 가능.
- UI 스레드 : UI 컨트롤을 생성하고 이 컨트롤의 윈도우 핸들을 소유한 스레드
- Worker 스레드 : 이런 UI 스레드를 갖지 않는 스레드
예제
using System.Threading;
namespace FrmEx10
{
public partial class Form1 : Form
{
private Thread m_thread = null;
public Form1()
{
InitializeComponent();
m_thread = new Thread(new ThreadStart(ThreadProc));
m_thread.Start();
}
private void ThreadProc()
{
int count = 0;
while (true) {
SetTextBox(count);
count++;
if (count == 10)
break;
}
}
private void SetTextBox(int count)
{ //여기서 중단점 (F9)
txtOutput.Text = count.ToString() + "번째";
// 이부분에서
//InvalidOperationException
//크로스 스레드 작업이 잘못되었습니다. txtOutput컨트롤이 자신이 만들어진
//스레드가 아닌 스레드에서 액세스되었습니다.
}
}//Form1
}//namespace
이를 해결하기위해서 Control.InvokeRequired를 확인해야 한다.
InvokeRequired
- 다른 Thread로부터 호출되어 Invoke가 필요한 상태를 체크해서 true / false 리턴
- invoke가 필요한 상태일때,
invoke메소드에 의해 호출될 델리게이트로 넘겨서 실행시키면 안정성있게 UI 갱신.
> 해당 컨트롤의 InvokeRequired 를 확인해서, true라면 delegate를 수행시킨다
public delegate void dgtSetBox(int count); // 델리게이트 생성
private void SetTextBox(int count)
{
if (textBox1.InvokeRequired) //InvokeRequired가 true이면
{
dgtSetBox dgt = new dgtSetBox(SetTextBox);
this.Invoke(dgt, new object[] { count });
}
else
{
txtOutput.Text = count.ToString() + "번째";
}
}
'프로그래밍&IT > C#' 카테고리의 다른 글
Thread 관련 간단 정리1. Thread / ThreadStart / ParameterizedThreadStart (0) | 2015.12.13 |
---|---|
Params 한정자, 매개변수 배열 (0) | 2015.09.07 |
System.Threading 네임 스페이스 및 Thread클래스 관련 (0) | 2015.04.11 |
C# System.Collections 인터페이스 & 클래스들 (0) | 2015.04.06 |
C# DataTable에서 Datarow 핸들링, Add select Update Delete (0) | 2015.04.06 |