비동기에 대한 기초적 개념을 알고 싶다면 MSDN 을 보는편이 훨신 좋을 것이다.
비동기 실행 방식에는 Task, Thread, Async, Await 등의 문법이 존재하는데.
그 중 Async 와 await 을 lamdba 식에서 사용시 오류에 관해 간단히 설명해 보려 한다.
아래 예제에서 Task1 을 실행시키면 Run() 비동기평선이 제대로 실행되지 않고 종료 될 것이다.
초보자가 보기엔 이것이 '버그' 일 수 있으나, 엄밀히 말하면 버그는 아니다.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
namespace AsyncAwaitExample
{
class Program
{
static async Task Run()
{
Console.WriteLine("Run 진입");
var task = Task.Run(()=>
{
for (int i = 0; i < 1000; ++i)
{
Console.WriteLine("Sum {0} 번째 계산", i);
}
});
await task;
}
public static void Main(String[] args)
{
// 비동기 Async 의 lambda 오류는 컴파일러 관점에서 살펴보면 그 원인을 알 수 있다.
// 1. 일단 Start(), () 와 함께 '동기식' 으로 함수가 실행된다.
// 2. async 함수 내의 await 을 만나게 되면, 여기서 해당 함수 (람다식이던 뭐던) 의 반환형이 반환된다.
// 3. 일반적인 동기식에서 그 반환형이 'Task' 이기에 문제가 되지 않는다. (바로 그 Task 가 끝나길 기다리는것)
// 4. 하지만 Task lambda 식의 경우 반환식이 void 형이다.
// 5. lambda 의 반환값인 void 형을 받은 '호출자' 는 이제 반환받은 Task 를 이용하여 '동기' 될 때 까지 대기할 수 있다.
// 6. 이걸 위한게 Wait() 함수이다. 반환받은거 끝나기 전까지 프로그램 끄지 말라고!
// 7. 근데 왠걸 lambda 식에서 반환한게 Task 가 아니라 void? 네?
// 8. 어쩌라는거냐, 대기할 작업이 없네? 뒤져야지...
//Code : new Task
//Task task1 = new Task(async () =>
//{
// await Run();
//});
//task1.Start();
//task1.Wait(); // 리턴값이 void 이다, 대기하는것이 불가능하다.
// 반대로 Func<Task> 는 다르다.
// 1. Func<Task> 의 오버로딩 형을 보면 알겠지만 여기서 <Task> 는 '반환형' 이다.
// 2. 함수 내에서 Run async 에 대해서 await 을 만나면 일단 이걸 반환때림.
// 3. 그럼 호출자 측에서 Wait(); 함수에서 비동기로 돌리다가 동기로 바꾸라는걸로 알아듣고 존버탈건데.
// 4. 반환식인 <Task> 에는 await Run() 작업이 들어있음
// 5. ok 받환받은 Task 끝날때까지 기다려줄게, (아까는 Void 여서 언제끝나는지도 모르는거지)
// 6. 사이좋게 Synchronize → Exit
//Func<Task> task2 = async () =>
//{
// await Run();
//};
//task2().Wait();
// 이친구는 Func를 쓰지 않아도 된다.
// 왜냐면 Task.Run 의 반환식은 Task 이기 때문이다.
//Task task3 = Task.Run(async () =>
//{
// await Run();
//});
//task3.Wait();
//Console.WriteLine("End");
}
}
}
직접 Task1, Task2, Task3 를 주석 해제하여 테스트해 보는걸 추천한다.
Task1 에서 해당 증상이 나타난다.
끝.
'Programming > C#' 카테고리의 다른 글
[C#] Struct 마샬링 및 사용법 (0) | 2021.04.15 |
---|---|
[C#] C# 에서 대괄호가 가지는 의미, (사전 정의된 속성, 특성) (0) | 2021.04.03 |
[C#] 델리게이트와 이벤트의 차이점 (0) | 2021.03.04 |
[C#] IEnumerable 인터페이스 상속 및 객체 열거형 만들기 (0) | 2021.03.03 |
[C#] 형변환 [as, is] (0) | 2021.02.27 |