본문 바로가기
PROGRAMING📚/Unity📑

[UNITY]비동기 작업 : Task 메서드 사용하는 방법

별찌루 2024. 4. 8.
728x90
반응형
 

[UNITY]비동기 프로그램 만들기: async / await

비동기 프로그램 만들기: async / await 프로그래밍 방식에는 동기식과 비동기식이 있다 동기식은 순차적인 실행 방식을 의미하고 일반적으로 동기식 작업 방식으로 진행이 된다 비동기식은 동기

j2su0218.tistory.com

 

Task / Task<TResult>

 

Task 메서드를 사용하기 위해서는using System.Threading.Tasks; 네임스페이스가 필요하다

using System.Threading.Tasks;

 

 

비동기 메서드의 반환 형식을 크게 3가지로 나누었을 때

 

Task 는 작업을 수행하지만 아무 값도 반환하지 않는 비동기 메서드의 경우에 사용하고

Task<TResult>는 값을 반환하는 비동기 메서드의 경우 사용하고

void 는 이벤트 처리기의 경우에 사용한다

 

 

Task 반환형식

 

return 문을 포함하지 않거나 피연산자를 반환하지 않거나

return 문을 포함하는 비동기 메서드의 반환 형식을 일반적으로 Task 이다

*동기적으로 반환하는 경우 void 를 반환한다 *

 

Task는 await 연산자를 사용해서 호출된 작업이 끝날 때 까지 완료를 일시 중단 할 수있다

 

다음 예시는 반환 값이 없는 Task의 사용 예제이다

public class TaskTest : MonoBehaviour
{
    private void Start()
    {
        Debug.Log($"{DateTime.Now:D}");
        Task.Run(() => DisplayCurrentInfoAsync());
    }
    public static async Task DisplayCurrentInfoAsync()
    {
        await WaitAndApologizeAsync();

        Debug.Log($"Today is {DateTime.Now:D}");
        Debug.Log($"The current time is {DateTime.Now.TimeOfDay:t}");
    }

    static async Task WaitAndApologizeAsync()
    {
        Debug.Log("Sorry for the delay...\n");
        await Task.Delay(2000);
        Debug.Log("Finish...\n");
    }
}

 

결과는 다음과 같이 나온다

 

  await Task.Delay(2000); 는 2초 대기 라는 뜻이다

1000 은 1초 라고 생각하고 Delay를 사용할 때 응용하면 된다

 

await 문에 의해서 WaitAndApologizeAsync()가 호출되고

2초 대기후 출력된다

하지만 위의 Task 함수는 Result 속성이 없기 때문에 값이 산출 되지 않는다

 

Task<TResult> 반환형식

 

피연산자가 TResult 인 return 문이 포한된 비동기 메서드에서 사용한다

int 형을 반환하는 비동기 메서드를 생성하려면

Task<int> 와 같이 생성해주면된다

 

 Task<TResult>는 TResult 형식의 Result 속성을 포함하고 있다

await가 GetLeisureHoursAsync() 에 적용되는 경우 

해당 작업이 완료되기 전에 접근하려고 하면, 작업이 완료되고 값을 사용할 수 있을 때까지 현재 활성화된 스레드가 차단된다

대부분의 경우 함수에 직접 접근하지 않고 await를 사용하여 값에 접근해야한다

 

다음 예시는 정수를 반환하는 GetLeisureHoursAsync() 메서드를 이용해서

오늘이 금요일이거나 일요일이면 16을 출력하고

아니면 5를 출력하는 함수이다 

 

    public static async Task ShowTodaysInfoAsync()
    {
        string message =
            $"Today is {DateTime.Today:D}\n" +
            "Today's hours of leisure: " +
            $"{await GetLeisureHoursAsync()}";

        Console.WriteLine(message);
    }

    static async Task<int> GetLeisureHoursAsync()
    {
        DayOfWeek today = await Task.FromResult(DateTime.Now.DayOfWeek);

        int leisureHours =
            today is DayOfWeek.Friday || today is DayOfWeek.Sunday
            ? 16 : 5;

        return leisureHours;
    }

 

ShowTodaysInfoAsync() 메서드의 await GetLeisureHoursAsync()을 호출 하며

GetLeisureHoursAsync()의 반환형 int 값을 가져오는 방식이다

GetLeisureHoursAsync()에서 사용된 await Task.FromResult(); 는

완료된 Task의 결과를 실어서 보낼 수 있다

 

Task 메서드

Task.Run()

 

동기 메서드 안에서 비동기 메서드를 호출할 때

Task.Run() 을 사용한다

 

Task.Run()에서는  CPU가 오래 처리해야하는 코드를 비동기 처리하는데 주로 사용된다

 

다음 예시는 비동기 메서드를 사용해서 콘솔창에 0-99개의 숫자를

출력하는 방법을 작성 해보았다

 

async void 형식 사용해서 출력하기

 

        private void Start(){
          printNumberVoid();
          Debug.Log("사용 예제");
        }
        private async void printNumberVoid(){
            await printNumberTask();
        }
        private async Task printNumberTask(){
            await Task.Run(()=>{
                for(int i=0; i<100; i++){
                    Debug.Log(i);
                }
            });
        }

위의 코드를 실행시키면 다음과 같이  출력이 된다

별차이를 모르겠다 싶어서 비동기처리를 사용하지 않고 출력을 해보았다

 

아래의 코드는 비동기를 사용하지 않은 일반적인 0-99까지 출력하는 함수이다

        private void printNumber()
        {
            for (int i = 0; i < 100; i++)
            {
                Debug.Log(i);
            }
        }

위 함수를 출력하면 다음과 같이 나온다

 

printNumber() 함수가 모두 출력되고

사용 예제 콘솔이 뜨는 것을 확인 할 수 있다

 

비동기 함수를 사용하지 않으면 async 를 지워주지 않으면 오류가 생긴다

별 문제 없어보이지만 await 가 존재 하지 않으면 무한루프에 걸려서 동작이 멈추니 조심하자

 

 

[ 참고 ]

더보기
728x90
반응형

댓글