thread join 사용
안녕하세요. .thread 연습 하다가 물어 볼꺼 있어서요...
Winform에 쓰레드를 생성했습니다.
thread 파일을 초기엔 null로 했습니다.
그리고 작업을 진행하다가 아래 StartThread를 호출 합니다.
private void StartThread()
{
if (thread == null)
{
thread = new Thread(new ThreadStart(GoThread);
GoThread.IsBackground = true;
GoThread.Priority = GoThread.Normal;
GoThread.Start();
}
if (!GoThread.IsAlive)
{
GoThread.Start();
}
GoThread.Join(); // 호출 함수가 끝날때까지 대기 해보자. -- 여기 질문
thread = null; // null을 넣는건 좀 부담 스러움
}
// 쓰레드 함수 진행
void GoThread()
{
try
{
while (queue.Count != 0)
{
// 큐에 쌓여 있는 작업 진행
queue.Dequeue();
// 쓰레드 안에 있으니 아래 처럼 인보크 사용해서 지행
this.Invoke((MethodInvoker)delegate
{
textBoxOutputLog.Text = ResultLog;
});
Thread.Sleep(1);
}
}
// 작업 완료 아래 처럼 null을 쓰고 싶은데 null을 넣기에는 부담 그래서 호출한 함수에서 join으로 대기해보자.
//thread= null;
}
질문 입니다.
GoThread.Join() 을 하니깐 쓰레드 함수가 다 종료가 될때까지 formview가 멈춥니다.
흠.... 원래 join이 스레드가 종료될때까지 기다린다는건 알겠는데 UI 진행도 멈추는건지 궁금 하네요...
그리고 쓰레드에 null을 넣는건 좋은 방법 인가요?
아 그리고 이건 부가적인 질문인데 ..
클레스가 생성하면 자동으로 종료되는건 알고 있습니다. 프로그램에서 직접 종료하는 방법 없을까요?? 이유을 설명하자면
클래스 생성 . 작업 진행 .. 진행중 쓰레드 처리 ... 쓰레드 처리 끝... (할일을 다함).. 종료... (이게 너무 오래 걸림)
C++에는 delete 가 있는데 ..
어째거나 이렇습니다.
回答 4
0
엄청난 열정에 놀랐습니다. ㅎㅎ 아래에 AI 답변도 존재하지만 추가로 정리해드리겠습니다.
WinForms에서 Join() 사용 시 UI 멈춤현상
메인(UI) 쓰레드에서
GoThread.Join()을 호출하면, 해당 쓰레드가 종료할 때까지 현재 쓰레드에서 대기하게 됩니다.UI와 관련된 처리는 모두
메인 스레드에서 이뤄지므로 Join()에서 대기하는 동안 폼이 멈춘것 처럼 보이게 돼요.
**해결방안**
쓰레드 작업이 끝나는 것을 기다리면서 UI가 멈추지 않게 하려면,
Join()을 직접 호출하지 말고, 쓰레드 작업이 끝났을 때 UI에 알리거나(예: 이벤트, 콜백),
BackgroundWorker, Task, async/await 등 비동기 프로그래밍 패턴을 사용하는 것이 좋습니다.
(일반적으로async/await를 가장 추천 드립니다.)
쓰래드 객체를 null로 설정하는 것?
쓰레드가 끝나면, 해당 Thread 객체는 더 이상 사용할 수 없으므로 필요하면 null로 만들어주는 것도 괜찮은 방법입니다. (null 을 할당하여 참조를 해제해주면 가비지 컬렉터가 빠르게 수거할 수 있어요.)
하지만 꼭 null로 만들 필요는 없고 쓰래드가 살아있는지(IsAlive 속성)만 체크해서 필요할 때 Thread객체를 새로 만들어도 괜찮습니다.
C#에서 클래스의 명시적 종료(소멸) 방법
C#에는 C++의 delete처럼 객체를 “즉시” 소멸시키는 문법이 없습니다.
C#의 객체는 해당 객체를 참조하는 곳이 없을 때(즉, 사용하지 않게 되었을 때)
가비지 컬렉터(GC)가 자동으로 메모리를 정리(소멸)합니다.IDisposable 인터페이스를 구현하고 Dispose()를 호출하는 것도 사실 메모리 자체는 GC가 회수하는 것 입니다.
0
위 질문에 이렇게 바꿔 봤어요 이게 더 좋을꺼 같긴한데 고칠 부분이 있을까요?
private void StartThread()
{
if (thread == null || !GoThread.IsAlive)
{
thread = new Thread(new ThreadStart(GoThread);
GoThread.IsBackground = true;
GoThread.Priority = GoThread.Normal;
GoThread.Start();
}
}
// 쓰레드 함수 진행
void GoThread()
{
try
{
while (queue.Count != 0)
{
// 큐에 쌓여 있는 작업 진행
queue.Dequeue();
// 쓰레드 안에 있으니 아래 처럼 인보크 사용해서 지행
this.Invoke((MethodInvoker)delegate
{
textBoxOutputLog.Text = ResultLog;
});
Thread.Sleep(1);
}
}
}
0
제시해주신 코드를 개선해보자면 아래와 같습니다.
private void StartThread()
{
if (thread == null || !thread.IsAlive)
{
thread = new Thread(GoThread);
thread.IsBackground = true;
thread.Priority = ThreadPriority.Normal;
thread.Start();
}
}
// 쓰레드 함수 예시 (queue를 thread-safe하게 사용)
void GoThread()
{
try
{
while (true)
{
object item = null;
lock (queue)
{
if (queue.Count == 0) break;
item = queue.Dequeue();
}
// UI 갱신
this.Invoke((MethodInvoker)delegate
{
textBoxOutputLog.Text = ResultLog;
});
// 필요에 따라 대기
Thread.Sleep(1);
}
}
}queue는 thread에 안전하지 않으므로 경합상태가 발생할 수 있습니다.
따라서 lock으로 감싸주는 것이 안전합니다.
또는 thread-safe한 System.Collections.Concurrent.ConcurrentQueue<T> 를 활용하는 방법도 있습니다. ConcurrentQueue 를 사용하면 lock으로 감싸주지 않아도 thread에 안전합니다.
ConcurrentQueue<string> queue = new ConcurrentQueue<string>();
queue.Enqueue(item);
queue.TryDequeue(out var result);
0
안녕하세요, 인프런 AI 인턴입니다. just kim님.
질문에서 언급하신 Thread.Join() 및 관련된 쓰레드 처리와 UI 멈춤 현상에 대해 설명드리겠습니다.
Thread.Join()의 영향:Thread.Join()메서드는 지정된 스레드가 완료될 때까지 현재 스레드의 실행을 차단합니다. WinForms에서 이 코드를 UI 스레드에서 호출하면, UI가 멈춘 것처럼 보이게 됩니다. 그 이유는 UI 스레드가 Join() 호출로 인해 대기 상태에 들어가게 되면서 다른 UI 이벤트를 처리할 수 없기 때문입니다.
- UI 응답성을 유지하려면
Join()을 UI 스레드가 아닌 다른 작업 스레드에서 사용하거나, 더불어 비동기 메서드를 활용하여 작업 완료를 기다리는 방법을 고려해야 합니다.
스레드에서 null 할당:
- 스레드를 종료하는 방법은
null을 할당하기보다는 스레드 작업이 자연스럽게 종료되도록 설계하는 것이 중요합니다.Thread.Join()을 사용하여 스레드가 종료할 때까지 기다린 뒤 이후 작업을 수행하는 방식으로 관리할 수 있습니다.
- 스레드를 중간에 강제로 종료하는 것은 안전하지 않으며, 일반적으로 작업 완료 확인 후 관련 변수에 null을 할당하여 스레드가 더 이상 참조되지 않도록 하는 방식이 사용됩니다.
- 스레드를 종료하는 방법은
클래스의 소멸:
- C#에서는 Garbage Collector가 비관리 리소스를 관리하기 때문에, C++의
delete와 같은 명시적인 해제 방법은 없습니다. 대신, 구현된 클래스가IDisposable인터페이스를 상속받아 리소스 정리를 수동으로 관리할 수 있습니다.
- 클래스 인스턴스에서
Dispose()메서드가 호출되도록 하고, 필요한 경우 그 안에 자원 해제를 구현할 수 있습니다.
- C#에서는 Garbage Collector가 비관리 리소스를 관리하기 때문에, C++의
이와 관련한 더 자세한 정보를 원하신다면 다음 링크를 참고하세요:
- C#에서 Thread 사용과 UI 응답성 유지하기
- IDisposable 인터페이스와 객체 소멸자 사용하기
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
UI있는 Designer 오류 발생 질문입니다.
0
73
2
CancelationTokenSource 질문이있습니다.
0
51
2
비동기 2강 UI가 없는 환경 질문입니다.
0
67
1
16_Collection 에서 Stack_ 후입선출에 질문입니다.
0
59
2
꼭 vs2022 로 다운받아야 하나요?
1
115
2
공부 문의드립니다,,
0
77
2
똑같이 따라서 ^1 했는데 에러가 떠요.
0
69
1
영상 구문 그대로 따라했는데 에러가 나요.
0
56
1
30강 듣고 질문이있습니다.
0
63
1
오늘 첫 강의를 들었습니다.
0
81
2
159번 강의 보는데 궁금한게 있습니다
0
63
3
asp.net blazor 강의는 현재 계획없으신가요
0
78
2
강의자료
1
171
2
메소드 호출이 되는이유?
0
77
1
~ 연산자 이해가 안되요
0
166
5
블로그 글
0
108
2
Delegate 내용은 어디서 다루나요?
0
107
2
Xunit private 메서드 테스트
0
121
2
자원정리 개념
0
113
2
강의 영상 오류
0
89
1
this string text의 동작 과정이 궁금합니다.
0
128
2
type변환 as에서 string과 int, int? 차이 질문입니다.
0
199
2
접근 제어자로 필드를 만들어 파생 클래스에서 사용할 때 질문입니다.
0
115
2
상속 부분 강좌에서 upcasting을 하는 이유가 궁금합니다.
0
134
2

