728x90
Task의 기본 개념
Task는 비동기 작업을 수행하기 위해 사용됩니다. 비동기 작업은 메인 스레드의 실행을 차단하지 않고, 병렬로 작업을 수행하거나 기다릴 수 있는 기능입니다. 이를 통해 작업이 완료될 때까지 기다리거나, 작업 완료 후의 동작을 할 수 있습니다.
Task의 주요 특징
- 비동기 작업의 결과를 반환할 수 있습니다.
- 병렬 처리를 지원합니다.
- await를 통해 작업이 완료될 때까지 기다릴 수 있습니다.
Task의 기본 사용법
using System.Threading.Tasks;
using UnityEngine;
public class TaskExample : MonoBehaviour
{
async void Start()
{
Debug.Log("작업 시작");
int result = await PerformDoubleTask(5);
Debug.Log($"결과: {result}");
}
private async Task<int> PerformDoubleTask(int number)
{
await Task.Delay(1000); // 1초 대기
return number * 2;
}
}
Start 메서드
- 이 코드에서는 async를 사용하여 비동기적으로 실행되며, PerformDoubleTask를 호출합니다.
PerformDoubleTask 메서드
- 숫자를 두 배로 만드는 비동기 작업을 정의합니다.
- 작업: 1초 대기(Task.Delay) 후 입력값을 두 배로 계산하여 반환합니다.
Task.Delay(1000)
- 비동기 작업을 시뮬레이션하기 위해 1초 동안 대기합니다.
- 작업의 실행은 일시 중단되지만, 메인 스레드는 블로킹되지 않아 다른 작업을 계속 실행할 수 있습니다.
await 키워드
- PerformDoubleTask의 완료를 비동기적으로 기다립니다.
- 대기가 끝난 후 반환값(두 배로 계산된 값)을 처리합니다.
실행 흐름
- Start 호출: 스크립트가 활성화되면 Start 메서드가 호출됩니다.
- PerformDoubleTask 호출: 5를 사용하여 비동기 작업을 실행합니다.
- 1초 대기: Task.Delay(1000)로 인해 1초 동안 대기합니다.
- 결과 반환: 1초 후, 입력값 5가 두 배로 계산되어 10을 반환합니다.
- 결과 출력: 결과를 콘솔에 출력합니다.
"작업 시작"
"결과: 10"
Task의 응용
Task 병렬 처리
Task.WhenAll은 여러 비동기 작업이 모두 완료된 후에야 다음 작업을 수행해야 할 때 유용합니다.
예제: 유니티에서 데이터 로드
async Task InitializeGame()
{
Task loadPlayerData = LoadPlayerDataAsync();
Task loadEnvironmentData = LoadEnvironmentDataAsync();
Task loadSettings = LoadSettingsAsync();
await Task.WhenAll(loadPlayerData, loadEnvironmentData, loadSettings);
Debug.Log("모든 데이터 로드 완료");
}
async Task LoadPlayerDataAsync()
{
await Task.Delay(1000); // 예: 서버에서 플레이어 데이터를 가져옴
Debug.Log("플레이어 데이터 로드 완료");
}
async Task LoadEnvironmentDataAsync()
{
await Task.Delay(1500); // 예: 맵 데이터를 가져옴
Debug.Log("환경 데이터 로드 완료");
}
async Task LoadSettingsAsync()
{
await Task.Delay(800); // 예: 게임 설정 데이터를 가져옴
Debug.Log("설정 데이터 로드 완료");
}
병렬 작업 후 결과 취합
Task.WhenAll은 모든 작업의 결과를 배열 형태로 반환합니다. 이를 통해 여러 작업의 결과를 하나로 취합할 수 있습니다.
예제: 서버에서 데이터 가져오기
async Task FetchGameData()
{
Task<int> playerLevelTask = GetPlayerLevelAsync();
Task<string> mapNameTask = GetMapNameAsync();
var results = await Task.WhenAll(playerLevelTask, mapNameTask);
int playerLevel = results[0]; // 첫 번째 Task 결과
string mapName = results[1]; // 두 번째 Task 결과
Debug.Log($"플레이어 레벨: {playerLevel}, 현재 맵: {mapName}");
}
async Task<int> GetPlayerLevelAsync()
{
await Task.Delay(1000); // 데이터베이스 호출 시뮬레이션
return 25; // 플레이어 레벨
}
async Task<string> GetMapNameAsync()
{
await Task.Delay(1200); // 데이터베이스 호출 시뮬레이션
return "Dragon Valley"; // 맵 이름
}
에러 처리
Task.WhenAll은 여러 작업 중 하나라도 예외가 발생하면 그 예외를 throw합니다. 하지만 모든 작업이 완료된 후에 예외를 확인할 수 있습니다.
예제: 오류를 포함한 비동기 작업
async Task PerformMultipleTasksWithErrorHandling()
{
try
{
Task task1 = SimulateTaskWithError("Task1");
Task task2 = SimulateTask("Task2");
await Task.WhenAll(task1, task2);
}
catch (Exception ex)
{
Debug.LogError($"작업 중 오류 발생: {ex.Message}");
}
}
async Task SimulateTaskWithError(string name)
{
await Task.Delay(500);
throw new Exception($"{name} 실패");
}
async Task SimulateTask(string name)
{
await Task.Delay(700);
Debug.Log($"{name} 성공");
}
Task.WhenAny 예제
async Task WaitForAnyTask()
{
Task task1 = SimulateTask("Task1", 1500);
Task task2 = SimulateTask("Task2", 1000);
Task firstCompleted = await Task.WhenAny(task1, task2);
Debug.Log($"{firstCompleted.Id}가 먼저 완료됨");
}
async Task SimulateTask(string name, int delay)
{
await Task.Delay(delay);
Debug.Log($"{name} 완료");
}
Task.WhenAll과 Task.WhenAny의 차이
- Task.WhenAll: 모든 작업이 완료될 때까지 기다림. 결과 배열을 반환하거나 예외를 throw합니다.
- Task.WhenAny: 첫 번째로 완료된 작업을 기다림. 어떤 작업이 완료되었는지 반환합니다.
Unity에서 Task를 사용해야 할 상황
Unity에서 Task는 주로 Unity 외부의 비동기 작업이나 성능 최적화를 위한 병렬 처리에 사용됩니다.
Unity 게임 개발의 Task 사용 예시
HTTP 요청 처리 - UnityWebRequest보다 더 복잡한 요청이 필요한 경우, Task를 통해 처리.
using System.Net.Http;
using System.Threading.Tasks;
using UnityEngine;
public class HttpExample : MonoBehaviour
{
private async void Start()
{
string data = await FetchData("https://api.example.com/data");
Debug.Log($"받은 데이터: {data}");
}
private async Task<string> FetchData(string url)
{
using HttpClient client = new HttpClient();
return await client.GetStringAsync(url);
}
}
파일 입출력 - 게임 데이터를 비동기로 저장하고 로드하여 메인 스레드의 성능 유지.
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
public class FileExample : MonoBehaviour
{
private async void Start()
{
string filePath = Application.persistentDataPath + "/data.txt";
await WriteToFile(filePath, "Hello, Task!");
string content = await ReadFromFile(filePath);
Debug.Log($"파일 내용: {content}");
}
private async Task WriteToFile(string path, string content)
{
await File.WriteAllTextAsync(path, content);
}
private async Task<string> ReadFromFile(string path)
{
return await File.ReadAllTextAsync(path);
}
}
728x90
'Unity > 정보' 카테고리의 다른 글
[Unity] Unity6 픽셀 아트 2D 라이팅 튜토리얼 (2) (0) | 2025.01.05 |
---|---|
[Unity] Unity6 픽셀 아트 2D 라이팅 튜토리얼 (1) (1) | 2025.01.05 |
[Unity] UniTask 유니티 비동기 프로그래밍 (0) | 2024.12.19 |
[Unity] 로컬 알림 기능 (Android) (0) | 2024.11.10 |
[Unity] Resources.UnloadUnusedAssets() : 메모리 관리 (0) | 2024.09.28 |