일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Data Structure
- Python
- C언어 포인터
- HTML
- 도커
- 플러터
- git
- Flutter
- 포인터
- c# 추상 클래스
- 깃
- c# winform
- c언어
- 유니티
- github
- C# delegate
- Houdini
- jupyter
- c#
- C++
- dart 언어
- docker
- 다트 언어
- Unity
- 구조체
- Algorithm
- gitlab
- vim
- c# 윈폼
- jupyter lab
- Today
- Total
nomad-programmer
[Programming/C#] 스레드 인터럽트 (Thread Interrupt) 본문
스레드는 수명이 다해 스스로 종료되는 것이 가장 좋지만, 불가피하게 스레드를 강제로 종료시켜야 하는 경우가 있다.
Abort() 메소드를 사용할 때는 도중에 강제로 중단된다 해도 프로세스 자신이나 시스템에 영향을 받지 않는 작업에 한 해 사용하는 것이 좋다.
스레드가 수행 중인 작업이 강제로 중단되는 경우 시스템에 악영향을 미칠 수 있다면 조금 더 부드러운 방법을 택해야 한다.
Thread.Interrupt() 메소드는 스레드가 한참 동작 중인 상태(Running 상태)를 피해서 WaitJoinSleep 상태에 들어갔을 때 ThreadInterruptedException 예외를 던져 스레드를 중지 시킨다. Abort()와 비슷하지만 Thread.Interrupt() 메소드가 조금 더 나은 방법이라 할 수 있다.
Thread.Interrupt() 메소드는 스레드가 이미 WaitSleepJoin 상태에 있을 때는 즉시 중단시키지만, 이 상태가 아닌 경우에는 스레드를 지켜보고 있다가 나중에 WaitSleepJoin 상태가 되면 그제서야 스레드를 중단시킨다. 이런 특징 때문에 프로그래머는 최소한 코드가 "절대로 중단되면 안 되는" 작업을 하고 있을 때에는 중단되지 않는다는 보장을 받을 수 있다.
- 스레드가 WaitSleepJoin 상태일 때, Interrupt()를 호출하면 즉시 ThreadInterruptedException 발생
- 스레드가 Running 상태일 때, Interrupt()를 호출해 두면 "나중에" WaitSleepJoin 상태가 됐을 때 ThreadInterruptedException 발생
static void DoSomething()
{
try
{
for(int i=0; i<1000; i++)
{
Console.WriteLine("DoSomething: {0}", i);
Thread.Sleep(10);
}
}
catch (ThreadInterruptedExcetion err)
{
// ...
}
finally
{
// ...
}
}
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(DoSomething));
t1.Start();
// 스레드 취소(종료)
t1.Interrupt();
t1.Join();
}
AbortingThread와 대부분 비슷하다. 차이점이라면 Abort() 메소드 대신 Interrupt() 메소드를 호출한다는 것과 ThreadStart 대리자가 참조하는 SideTask.KeepAlive() 메소드의 시작 부분에서 SpinWait() 메소드를 호출함으로써 Interrupt() 메소드가 호출될 때 스레드의 상태가 한동안 Running 상태를 갖도록 하게 했다는 것 정도이다.
using System;
using System.Threading;
namespace CSharpExample
{
class SideTask
{
private int count;
public SideTask(int count) => this.count = count;
public void KeepAlive()
{
try
{
Console.WriteLine("Running thread isn't gonna be interrupted");
// 메소드는 Sleep()과 유사하게 스레드를 대기하도록 하지만 Sleep()과는 달리
//스레드가 Running 상태를 유지하게 한다.
Thread.SpinWait(1000000000);
while (count > 0)
{
Console.WriteLine($"{ count--} left");
Console.WriteLine("Entering into WaitJoinSleep State...");
Thread.Sleep(10);
}
Console.WriteLine("Count: 0");
}
catch (ThreadInterruptedException err)
{
Console.WriteLine(err);
}
finally
{
Console.WriteLine("Clearing resource...");
}
}
}
internal class MainApp
{
static int Main(string[] args)
{
SideTask task = new SideTask(100);
Thread t1 = new Thread(new ThreadStart(task.KeepAlive));
t1.IsBackground = false;
Console.WriteLine("Starting thread...");
t1.Start();
Thread.Sleep(100);
Console.WriteLine("Interrupting thread...");
t1.Interrupt();
Console.WriteLine("Waiting until thread stops...");
t1.Join();
Console.WriteLine("Finished");
return 0;
}
}
}
/* 결과
Starting thread...
Running thread isn't gonna be interrupted
Interrupting thread...
Waiting until thread stops...
100 left
Entering into WaitJoinSleep State...
System.Threading.ThreadInterruptedException: 스레드가 대기 상태에서 인터럽트되었습니다.
위치: System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
위치: System.Threading.Thread.Sleep(Int32 millisecondsTimeout)
위치: CSharpExample.SideTask.KeepAlive() 파일 D:\workspace\c#\study\this_is_csharp\HelloWorld\HelloWorld.cs:줄 26
Clearing resource...
Finished
*/
SpinWait() 메소드는 별로 쓸 일이 없다. 이 메소드는 Sleep()과 유사하게 스레드를 대기하게 하지만 Sleep()과는 달리 스레드가 Running 상태를 유지하게 한다.
이 메소드를 사용한 것은 Interrupt() 메소드를 호출하는 시점에 스레드가 Running 상태를 유지하도록 하기 위함이다. Interrup() 메소드가 호출된 스레드는 Thread.Sleep(10)에 의해 WaitSleepJoin 상태에 들어가고, 이 때 인터럽트가 발생한다.
'Programming > C#' 카테고리의 다른 글
[Programming/C#] const (상수화)와 readyonly (읽기전용)의 차이점 (0) | 2020.09.29 |
---|---|
[Programming/C#] 스레드 동기화 (Thread Synchronization) (0) | 2020.09.29 |
[Programming/C#] 스레드의 일생과 상태 변화 (0) | 2020.09.29 |
[Programming/C#] 스레드 임의 종료 (Abort) (0) | 2020.09.28 |
[Programming/C#] 스레드 (Thread) (0) | 2020.09.28 |