C#에서 async/await 해석

카탈로그
  • 앞말:
  • 1. async와await
  • 사용
  • 2. 코드로 async/await
  • 구현

    선언:
    이미 많은 문장이 async/await를 설명하였는데, 이 문장은 단지 자신에게 이해용으로만 쓰인다.이 글은 다음 코드를 반복해서 사용하여 전문을 관통시킬 것이다
        public static string GetThreadId()
        {
         
            return Thread.CurrentThread.ManagedThreadId.ToString("000");
        }
        
        public static void TaskRun()
        {
         
            Console.WriteLine($"======== ThreadId:{GetThreadId()} Start.");
            Thread.Sleep(3000);
            Console.WriteLine($"======== ThreadId:{GetThreadId()} End.");
        }
    

    1. async와 await 사용
    async/await를 사용합니다.
    	// btnAsync        
        private void btnAsync_Click(object sender, EventArgs e)
        {
         
            Task task = NoReturnTask();
        }
        
        private async Task NoReturnTask()
        {
         
            Console.WriteLine($"==== ThreadId:{GetThreadId()} Start.");
            await Task.Run(() => TaskRun());
            Console.WriteLine($"==== ThreadId:{GetThreadId()} End.");
        }
    

    2. 코드로 async/await 실현 1의 코드를 ILSpy로 역컴파일한 후에 우리는 async와 await가 하나의 상태기로 컴파일된 것을 발견할 수 있다.
    	// btnAsync2         
        private void btnAsync2_Click(object sender, EventArgs e)
        {
         
            var stateMachine = new AsyncStateMachine();
            stateMachine.builder = AsyncTaskMethodBuilder.Create();
            stateMachine.state = -1;
            stateMachine.builder.Start(ref stateMachine);
            Task task = stateMachine.builder.Task;
        }
    
        private class AsyncStateMachine : IAsyncStateMachine
        {
         
            public int state;
            public AsyncTaskMethodBuilder builder;
            private TaskAwaiter taskAwaiter;
    
            public void MoveNext()
            {
         
                int num = state;
                try
                {
         
                    TaskAwaiter awaiter;
                    if (num != 0)
                    {
         
                        Console.WriteLine($"==== ThreadId:{GetThreadId()} Start.");
                        awaiter = Task.Run(() => TaskRun()).GetAwaiter();
                        if (!awaiter.IsCompleted)
                        {
         
                            num = state = 0;
                            taskAwaiter = awaiter;
                            AsyncStateMachine stateMachine = this;
                            builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
                            return;
                        }
                    }
                    else
                    {
         
                        awaiter = taskAwaiter;
                        taskAwaiter = default;
                        num = state = -1;
                    }
                    awaiter.GetResult();
                    Console.WriteLine($"==== ThreadId:{GetThreadId()} End.");
                }
                catch (Exception ex)
                {
         
                    state = -2;
                    builder.SetException(ex);
                    return;
                }
    
                state = -2;
                builder.SetResult();
            }
    
            void IAsyncStateMachine.MoveNext()
            {
         
                MoveNext();
            }
    
            public void SetStateMachine(IAsyncStateMachine stateMachine)
            {
         
            }
    
            void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
            {
         
                SetStateMachine(stateMachine);
            }
        }
    

    전체 상태기의 집행 절차는 AsyncTaskMethodBuilderStart 방법 촉발IAsyncStateMachine.MoveNext 방법에서 시작한다.상태기에서 Task.Run로 우리가 기다려야 할 임무를 수행하고 TaskAwaiter로 임무의 완성 여부를 감시한다.작업이 완료되기를 기다리면 리셋 리셋 IAsyncStateMachine.MoveNext 방법이 있습니다. 이 때 상태기의state는 0이고 awaiter.GetResult 방법으로 실행되면 결과를 얻을 수 있습니다.

    좋은 웹페이지 즐겨찾기