성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - 작업자(Worker) 스레드와 UI 스레드</h1> <p> 작업자 스레드는 보통 UI 요소를 갖지 않는 스레드를 일컫습니다. 따라서, 다음과 같은 경우의 스레드는 보통 작업자 스레드라고 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Thread thread = new Thread(threadFunc); thread.Start(); private void threadFunc() { // 스레드 작업 } </pre> <br /> 이런 것도 작업자 스레드입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ThreadPool.QueueUserWorkItem( (arg) => { // 스레드 작업 }, null); </pre> <br /> 반면 UI 스레드는 스레드에서 UI 요소를 생성해 사용하는 것을 말합니다. 그런데, UI 요소를 생성했다고 UI 스레드가 아닙니다. 그 UI 요소가 잘 동작하려면 메시지 펌프를 위한 메시지 루프 처리가 있어야 합니다. Win32에서는 다음과 같이 처리하던 코드입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://docs.microsoft.com/en-us/windows/win32/winmsg/using-messages-and-message-queues'>https://docs.microsoft.com/en-us/windows/win32/winmsg/using-messages-and-message-queues</a> while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { if (bRet == -1) { // handle the error and possibly exit } else { TranslateMessage(&msg); DispatchMessage(&msg); } } </pre> <br /> 닷넷에서는 이러한 메시지 펌프를 Application.Run 함수에서 해줍니다. 따라서 다음의 스레드는 UI 스레드가 되는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Thread thread = new Thread(threadFunc); thread.Start(); private void threadFunc() { Application.Run(...[생략]...); } </pre> <br /> 물론, 스레드 풀에서 빌려온 스레드일지라도 메시지 루프를 가지면 UI 스레드가 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ThreadPool.QueueUserWorkItem( (arg) => { Application.Run(...); }, null); </pre> <br /> <hr style='width: 50%' /><br /> <br /> 실제로 테스트를 해볼까요? ^^ Form2 윈도우 코드를 다음과 같이 만듭니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form2 : Form { Timer _timer = new Timer(); // System.Windows.Forms.Timer는 타이머 처리를 // 내부적으로 윈도우 이벤트를 사용합니다. public Form2() { InitializeComponent(); _timer.Interval = 1000; _timer.Tick += Timer_Tick; _timer.Start(); } // 따라서, 아래의 함수는 이벤트 처리가 안되면 실행되지 않습니다. private void Timer_Tick(object sender, EventArgs e) { this.textBox1.Text = DateTime.Now.ToString(); } } } </pre> <br /> 위의 윈도우를 다음과 같이 작업자 스레드에서 실행해 봅니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ThreadPool.QueueUserWorkItem( (arg) => { Form2 form = new Form2(); form.Show(); }, null); </pre> <br /> 그럼 윈도우까지는 뜨는데 텍스트 박스에 있는 시간이 업데이트가 안됩니다. 물론 그 외에도 WM_PAINT 같은 이벤트도 처리가 안되므로 화면이 마치 hang이 걸린 듯한 현상이 발생합니다.<br /> <br /> 반면, 다음과 같이 UI 스레드에서 실행하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ThreadPool.QueueUserWorkItem( (arg) => { Form2 form = new Form2(); Application.Run(form); }, null); </pre> <br /> 이번에는 타이머 처리가 잘 되어 텍스트 박스가 1초마다 내용이 업데이트됩니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 자, 그럼 여기서 윈도우 프로젝트에 기본적으로 생성되는 Program.cs를 한번 열어봅니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); <span style='color: blue; font-weight: bold'>Application.Run(new Form1());</span> } } </pre> <br /> 바로 저 코드! 이제는 이해가 되시겠죠? 바로 메시지 루프이며 덕분에 UI 스레드로써 기능을 하고 있는 것입니다.<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
9548
(왼쪽의 숫자를 입력해야 합니다.)