해결된 질문
작성
·
66
0
안녕하세요. .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 답변도 존재하지만 추가로 정리해드리겠습니다.
메인(UI) 쓰레드에서 GoThread.Join()
을 호출하면, 해당 쓰레드가 종료할 때까지 현재 쓰레드에서 대기하게 됩니다.
UI와 관련된 처리는 모두 메인 스레드
에서 이뤄지므로 Join()에서 대기하는 동안 폼이 멈춘것 처럼 보이게 돼요.
**해결방안**
쓰레드 작업이 끝나는 것을 기다리면서 UI가 멈추지 않게 하려면,
Join()을 직접 호출하지 말고, 쓰레드 작업이 끝났을 때 UI에 알리거나(예: 이벤트, 콜백),
BackgroundWorker, Task, async/await 등 비동기 프로그래밍 패턴을 사용하는 것이 좋습니다.
(일반적으로 async/await
를 가장 추천 드립니다.)
쓰레드가 끝나면, 해당 Thread 객체는 더 이상 사용할 수 없으므로 필요하면 null로 만들어주는 것도 괜찮은 방법입니다. (null 을 할당하여 참조를 해제해주면 가비지 컬렉터가 빠르게 수거할 수 있어요.)
하지만 꼭 null로 만들 필요는 없고 쓰래드가 살아있는지(IsAlive 속성)만 체크해서 필요할 때 Thread객체를 새로 만들어도 괜찮습니다.
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
0
안녕하세요, 인프런 AI 인턴입니다. just kim님.
질문에서 언급하신 Thread.Join()
및 관련된 쓰레드 처리와 UI 멈춤 현상에 대해 설명드리겠습니다.
Thread.Join()
의 영향:
Thread.Join()
메서드는 지정된 스레드가 완료될 때까지 현재 스레드의 실행을 차단합니다. WinForms에서 이 코드를 UI 스레드에서 호출하면, UI가 멈춘 것처럼 보이게 됩니다. 그 이유는 UI 스레드가 Join() 호출로 인해 대기 상태에 들어가게 되면서 다른 UI 이벤트를 처리할 수 없기 때문입니다.Join()
을 UI 스레드가 아닌 다른 작업 스레드에서 사용하거나, 더불어 비동기 메서드를 활용하여 작업 완료를 기다리는 방법을 고려해야 합니다.스레드에서 null 할당:
null
을 할당하기보다는 스레드 작업이 자연스럽게 종료되도록 설계하는 것이 중요합니다. Thread.Join()
을 사용하여 스레드가 종료할 때까지 기다린 뒤 이후 작업을 수행하는 방식으로 관리할 수 있습니다.클래스의 소멸:
delete
와 같은 명시적인 해제 방법은 없습니다. 대신, 구현된 클래스가 IDisposable
인터페이스를 상속받아 리소스 정리를 수동으로 관리할 수 있습니다.Dispose()
메서드가 호출되도록 하고, 필요한 경우 그 안에 자원 해제를 구현할 수 있습니다.이와 관련한 더 자세한 정보를 원하신다면 다음 링크를 참고하세요:
- C#에서 Thread 사용과 UI 응답성 유지하기
- IDisposable 인터페이스와 객체 소멸자 사용하기
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
제시해주신 코드를 개선해보자면 아래와 같습니다.
queue는 thread에 안전하지 않으므로
경합상태
가 발생할 수 있습니다.따라서 lock으로 감싸주는 것이 안전합니다.
또는 thread-safe한
System.Collections.Concurrent.ConcurrentQueue<T>
를 활용하는 방법도 있습니다. ConcurrentQueue 를 사용하면 lock으로 감싸주지 않아도 thread에 안전합니다.