Task 쓰다가 궁금했던것
여기 부분은 나중에 더 알게되면 아는만큼 쓰던가 하고
지금은 궁금한거 만 늘어놓고 끝내기로.
- main과 현재 task의 thread가 다르다는것을 보일 수 있는가?
- “특정 task에서 실행이 오래걸림”의 재현을
THread.sleep()로 구현하는데 맞나?- 정확히 Thread.sleep는 어떤 Thread에 작용하는거??
- 예를들어 Task에 넘긴 Action에 연결된 method안에
Thread.Sleep()가 있다고 가정했을때 어떤 Thread가 sleep하나?
또, 원래 웹을 읽어온다거나 하는등의 시간이 걸렸을 작업을
Task안에 Thread.sleep로 구현하는게 맞나?
- Wait은 Task가 완료 될때까지
Task를 실행한 thread는 block돤다고 했는데 …- 그럼 왜쓰는거임?
main thread / task thread
- task는 thread pool의 thead에서 샐행 된다 했음.
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 32 33 34 35 36 37 38 39
class Program { static void Main(string[] args) { Console.WriteLine("Main={0}",Thread.CurrentThread.ManagedThreadId); new test_3(); } } class test_3 { public test_3() { Console.WriteLine("test_3={0}", Thread.CurrentThread.ManagedThreadId); mtd_1(); } void mtd_1() { Action<object> action = (object obj) => { Console.WriteLine("Task={0}, obj={1}, Thread={2}", Task.CurrentId, obj, Thread.CurrentThread.ManagedThreadId); }; Task t1 = new Task(action, "t1"); Task t2 = new Task(action, "t2"); Task t3 = new Task(action, "t3"); t1.Start(); t2.Start(); t3.Start(); t1.Wait(); t2.Wait(); t3.Wait(); } }
- 실행 결과는
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Main=1 test_3=1 Task=2, obj=t2, Thread=6 Task=3, obj=t3, Thread=5 Task=1, obj=t1, Thread=3 Main=1 test_3=1 Task=1, obj=t1, Thread=3 Task=3, obj=t3, Thread=6 Task=2, obj=t2, Thread=5 Main=1 test_3=1 Task=1, obj=t1, Thread=3 Task=2, obj=t2, Thread=4 Task=3, obj=t3, Thread=5
- 실행 결과는 대체적으로 할 때마다 순서가 바뀜.
- 위 실행 결과는 같은거 여러번한거.
- 1,2,3 start의 순서가 중요한게 아닌것같음
Thread.CurrentThread.ManagedThreadId로
확인할 때마다 id가 계속 달라진다.그래서.. 하는건데
Thread.으로 시작하는 static method들은
해당 부분을 실재로 실행하고있는 thread를 지징하는것같음
그래서 main, test_3은 main에서 왔으니 id = 1로 같고
task로 실행하는 부분은 task각각에 다른 thread id가 생긴다.
“특정 task에서 실행이 오래걸림”의 재현
- 위를 시작으로 조금 풀리는듯함.
- 일단, 위의 전제가 확실히 맞다고 하면
Task에 구현된 method안에 Thread.sleep은
실제 그 method를 실행하고있는 Task의 thread에 작용하겠지..
그럼 맞음.
wait()??
Task_2 에서
Wait(Int32)및 Wait(TimeSpan) 메서드는
작업이 완료 되거나 시간 제한 간격이 경과할 때까지
(둘 중 먼저 도달 하는 경우) 호출 스레드를 차단.이라고 했는데 애초에 이게 이상해서 위에 의문들이 계속 생긴듯함.
- Wait를 만나면 task를 호출한 thread는 차단되나?
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 32 33 34 35 36 37 38 39
class test_4 { public test_4() { Action<object> action = (object obj) => { Console.WriteLine(DateTime.Now.ToString("ss.fff")); Console.WriteLine("Task={0}, obj={1}, Thread={2}", Task.CurrentId, obj, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(1000); }; Task t1 = new Task(action,"t1"); Task t2 = new Task(action, "t2"); for (int i = 0; i < 10; i++) { Console.WriteLine("{0} : {1}",i, DateTime.Now.ToString("ss.fff")); if (i == 2) { t1.Start(); } else if (i == 6) { t1.Wait(); t2.Start(); t2.Wait(); } Thread.Sleep(1000); } } }
- 출력을 보면
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Main=1 0 : 07.877 1 : 08.892 2 : 09.905 09.910 Task=1, obj=t1, Thread=3 3 : 10.921 4 : 11.935 5 : 12.935 6 : 13.945 13.945 Task=2, obj=t2, Thread=4 7 : 15.951 8 : 16.964 9 : 17.978
Task 1 의 경우
t1.wait 만나기 전까지 Action이 끝날만한 충분한 시간이 있어서 잘 끝났는데Task 2 의 경우 t2.wait전에 끝나지 않아 시간을 잡아먹음.
class test_4는 main thread 이므로 t2.wait만나면서 끝날때까지 기다림.
흐름상 wait만나기 전까지 task가 끝나기 않으면 task를 호출했던 thread는 block됨.
wait 만나기 전까지 thread랑 task는 각각 따로 가는데
wait만났을 떄 해당 task가 끝나지 않은 상태면 thread가 기다려줌- 실행은 async인데 실제 method에서는 blocking이라 저런식인듯
- 이런점이 조금 이상했다.
- 보통 thread로 따로 빼는 작업들은 시간이 오래 걸려
main에서 처리를 안하게끔하는게 목적인데
이렇게 하면 별반 다를게 없어보인다.
어쨌건 wait만나면 UI는 멈춘것처럼 보일테니까. - wait()를 빼면 될것같은데 그것도 찝찝하긴함.
언제 끝날지 모르는 작업에 대해
끝을 정하지 않고 그저 실행만 하고 넘긴다는게 옳은일인가?
- 보통 thread로 따로 빼는 작업들은 시간이 오래 걸려
정리
- task는 async로 동작하나 여전히 block임.
- paramster, return이 있는경우 상관없음
- 더 자세한 내용은 기회가 된다면 나중에..
Comments powered by Disqus.