Home 9. Task_3
Post
Cancel

9. Task_3

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()를 빼면 될것같은데 그것도 찝찝하긴함.
      언제 끝날지 모르는 작업에 대해
      끝을 정하지 않고 그저 실행만 하고 넘긴다는게 옳은일인가?

정리

  • task는 async로 동작하나 여전히 block임.
  • paramster, return이 있는경우 상관없음
  • 더 자세한 내용은 기회가 된다면 나중에..

참고

작업 기반 비동기 프로그래밍 작업 기반 비동기 패턴

This post is licensed under CC BY 4.0 by the author.

8. Lambda expressions

10. async/await_2

Comments powered by Disqus.