1. 동기 프로그래밍, 비동기 프로그래밍
동기 프로그래밍(Synchronous Programming)이란, 프로그램이 실행되는 도중 어떤 작업을 요청하면, 그 작업이 종료될 때까지 기다렸다가 다음 작업을 하는 것을 의미합니다.
동기 방식은 요청과 결과가 동시에 일어나기 때문에, 설계가 매우 간단하고 직관적이지만, 작업이 완료될 때까지 프로그램이 대기해야 합니다.
비동기 프로그래밍(Asynchronous Programming)란, 프로그램이 실행 되는 도중 어떤 행위를 요청한 뒤 그 결과는 기다리지 않고, 다음 동작을 하는 것을 의미합니다.
비동기 프로그래밍은 설계 단계에서 동기보다 복잡하고, 요청한 작업이 완료될 때는 별도로 확인해야 하지만, 요청한 자료가 오래 걸린다고 하더라도 다른 작업을 계속할 수 있기 때문에 자원을 효율적으로 사용할 수 있습니다.
2. Task 클래스
2.1 Task 클래스
일반적으로 하나의 프로세스는 하나의 스레드를 가지고 작업을 수행합니다.
하지만 멀티 스레드(Multi Thread)란 하나의 프로세스에서 둘 이상의 스레드가 동시에 작업을 수행하느것을 의미합니다.
Task 클래스는 .Net 4.0부터 도입된 클래스로 멀티 스레드에서 비동기 작업을 실행합니다.
Task 클래스는 using 지시문을 사용하여 System.Threading.Tasks를 지시해 주어야 합니다.
네임스페이스 |
using System.Threading.Tasks; |
Task 사용하는 방법은 직접 호출, Action 대리자 사용, 대리자, 람다식, 람다와 익명 메서드 등이 있습니다.
using UnityEngine;
using System.Threading.Tasks;
using System;
public class TaskExample : MonoBehaviour
{
void Start()
{
Task.Factory.StartNew(() => { Debug.Log("Task"); }); // 직접 호출, 스레드 생성과 시작
Task task2 = new Task(new Action(DebugLog)); // Action 대리자
task2.Start(); // Task 스레드 시작
Task task3 = new Task(delegate { DebugLog(); }); // 대리자
task3.Start(); // Task 스레드 시작
Task task4 = new Task(() => DebugLog()); // 람다식
task4.Start(); // Task 스레드 시작
Task task5 = new Task(() => { DebugLog(); }); // 람다와 익명 메서드
task5.Start(); // Task 스레드 시작
task2.Wait(); // Task가 끝날 때까지 대기
task3.Wait(); // Task가 끝날 때까지 대기
task4.Wait(); // Task가 끝날 때까지 대기
task4.Wait(); // Task가 끝날 때까지 대기
}
void DebugLog()
{
Debug.Log("Task");
}
}
Task 메서드 |
설명 |
Factory.StartNew |
스레드 생성과 시작 |
Start |
Task 스레드 시작 |
Wait |
Task 끝날 때까지 대기 |
2.2 Task<T> 클래스
일반 Task는 변환값을 받지 못하지만, 제네릭 Task를 사용하면 변환값을 얻을 수 있습니다.
Result라는 속성으로 변환값을 얻을 수 있습니다.
using UnityEngine;
using System.Threading.Tasks;
public class GenericTaskExample : MonoBehaviour
{
void Start()
{
Task<int> task = Task.Factory.StartNew<int>(() => GetSize("GenericTask"));
int result = task.Result;
Debug.Log(result); // 출력 : 11
}
int GetSize(string data)
{
return data.Length;
}
}
2.3 Task 작업 취소
비동기 작업 취소하기 위해서는 Cancellation Token을 사용하는데, 작업 취소와 관련된 타입은 CancellationTokenSource 클래스와 CancellationToken 구조체입니다.
네임스페이스 |
using System.Threading; using System.Threading.Tasks; |
작업을 취소하는 일반적인 절차
① CancellationTokenSource 클래스 필드에서 선언
② CancellationTokenSource 객체를 생성
③ 비동기 작업 메서드 안에서 작업이 취소되었는지를 체크하는 코드(.Token.IsCancellationRequested)를 넣으며,
④ 취소 명령이 들어오면 CancellationTokenSource의 Cancel() 메서드를 호출해 작업 취소를 요청
using UnityEngine;
using System.Threading;
using System.Threading.Tasks;
public class CancellationTokenExample : MonoBehaviour
{
CancellationTokenSource m_CancelTokenSource; // ① CancellationTokenSource 클래스 필드에서 선언
Task<int> m_Task;
void Start()
{
m_CancelTokenSource = new CancellationTokenSource(); // ② CancellationTokenSource 객체를 생성
CancellationToken cancellationToken = m_CancelTokenSource.Token;
m_Task = Task.Factory.StartNew(TaskMethod, cancellationToken);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.C))
{
m_CancelTokenSource.Cancel(); // ④ CancellationTokenSource의 Cancel() 메서드를 호출해 작업 취소
if (m_Task != null)
{
Debug.Log("Count : " + m_Task.Result);
}
}
}
private int TaskMethod()
{
int count = 0;
for (int i = 0; i < 10; i++)
{
if (m_CancelTokenSource.Token.IsCancellationRequested) // ③ 비동기 작업 메서드 안에서 작업이 취소되었는지를 체크
{
break;
}
++count;
Thread.Sleep(1000);
}
return count;
}
}
3. async, await
C# 5.0부터 추가된 키워드 async와 await는 비동기 프로그래밍을 지원하는 키워드입니다.
async는 해당 메서드가 awiat를 가지고 있음을 알려 줍니다.
Task 메서드 |
설명 |
Run |
비동기 시작 |
FromResult |
비동기 시작 후 결과값을 얻음. |
using UnityEngine;
using System.Threading;
using System.Threading.Tasks;
public class AsyncAwaitExample : MonoBehaviour
{
void Start()
{
TaskRun();
TaskFromResult();
}
async void TaskRun()
{
var task = Task.Run(() => TaskRunMethod(3));
int count = await task;
Debug.Log("Count : " + task.Result); // 출력 : Count : 3
}
private int TaskRunMethod(int limit)
{
int count = 0;
for (int i = 0; i < limit; i++)
{
++count;
Thread.Sleep(1000);
}
return count;
}
async void TaskFromResult()
{
int sum = await Task.FromResult(Add(1, 2));
Debug.Log(sum); // 출력 : 3
}
private int Add(int a, int b)
{
return a + b;
}
}
'프로그램 > 유니티 C# 강좌' 카테고리의 다른 글
[유니티 C# 강좌] 21. 제네릭 컬렉션(General Collection) (1) | 2020.02.09 |
---|---|
[유니티 C# 강좌] 20. 병렬 프로그래밍 (Parallel Programming) (0) | 2020.02.09 |
[유니티 C# 강좌] 18. 익명 형식, 익명 메서드, 람다식, Func 대리자, Action 대리자 (0) | 2020.02.05 |
[유니티 C# 강좌] 17. 이벤트(Event), 대리자 (델리게이트, Delegate) (0) | 2020.02.04 |
[유니티 C# 강좌] 16. 전처리기 지시어(Preprocessor Directive) (0) | 2020.01.30 |