티스토리 뷰

반응형

.Net Framework 4.5에서 아주 많이 사용되고 있는 Task, Async, Await에 대해서 설명을 하려고 한다.

 

기존 .Net Framework 4.0에서는 async, await라는 키워드 세트를 이용해서 멀티 스레드 처리를 하지 않고, 별도의 스레드 관리 방법으로 사용을 했다. 그런데, 사용이 쉽지 않고, 관리가 어려워서 잘 사용을 하지 않은 것 같다. MS에서도 그 점을 알았는지, 쉽고 편하게 멀티스레드를 사용할 수 있도록 만들고, .Net Framework 4.5는 Async 기반 프레임웍이라고 이야기를 했다.

 

참고 링크

Best Practices in Asynchronous Programming

http://msdn.microsoft.com/en-us/magazine/jj991977.aspx

간편한 비동기 프로그래밍:async/await (1) -> 동기 비동기에 관한 기본적인 내용에 대해서 알아보기 좋내요

http://www.simpleisbest.net/post/2013/02/06/About_Async_Await_Keyword_Part_1.aspx

 

 

1. 데이터 로딩 작업(1)

앱이 구동된 후에 3가지 데이터를 로딩 하는 작업이 있다고 가정하자.

셈플 코드를 만들면 아래와 같다.

 

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            DataLoding();
        }

        private void DataLoding()
        {
            DataLoading1();
            DataLoading2();
            DataLoading3();

            listBox.Items.Add("DataLoading...");
        }

        private async void DataLoading1()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading1 Complete");
        }

        private async void DataLoading2()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading2 Complete");
        }
       
        private async void DataLoading3()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading3 Complete");
        }

실행을 한다. xaml에는 ListBox를 한개 추가해 놓았다.

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <ListBox x:Name="listBox" FontSize="48"/>
    </Grid>

 

 

3개의 데이터가 모드 로드 완료되었다. 그런데, 이상한 점은 시작은 1,2,3 순서로 했는데 표시된 순서는 2,1,3으로 표시가 되어있다.

위의 소스처럼 각 메소드를 async, void 호출을 하면,

장점은 Main Thread에서 await를 하지 않기 때문에 각 메소드가 Work Thread로 분리되어서 처리가 진행 되어, 화면 진행에 Lock을 발생시키지 않는 것이다. 그래서, DataLoading...이라는 글씨가 맨 위에 들어가고 나머지 완료 메시지들이 아래 부분에 표시된다.

단점은 완료 시점을 명확하게 알 수 없다는 부분과, 어떤 작업 순서에 의해, 제일 중요한 데이터 실행 후 다른 작업을 진행해야하는데, 그렇게 할 수 없다는 것이다.

 

 

2. 데이터 로딩 작업(2)

DataLoading1번 작업이 완료된 후에 DataLoading2, 3번 작업이 진행되도록 진행 순서를 변경하여 보자.

 

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            DataLoding();
        }

        private async void DataLoding()
        {
            await DataLoading1();
            DataLoading2();
            DataLoading3();
            listBox.Items.Add("DataLoading...");
        }

        private async Task DataLoading1()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading1 Complete");
        }

        private async void DataLoading2()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading2 Complete");
        }
       
        private async void DataLoading3()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading3 Complete");
        } 

 

 

위의 결과를 보면 DataLoading1 작업이 완료된 후 나머지 작업들이 완료된 모습을 볼 수 있다.

소스를 보면 굵게 표시한 부분이 변경된 것들이다.

 

일반적인 경우라면 위의 처리 방법으로 처리를 해도 무난할 것이라고 생각된다.

 

3. 데이터 로딩 작업(3)

 

여기서 모든 작업 완료 후 DataLoading all complete라는 메시지를 출력해야 한다면 어떻게 해야할까?

 

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            DataLoding();
        }

        private async void DataLoding()
        {
            listBox.Items.Add("DataLoading...");
            await DataLoading1();
            await DataLoading2();
            await DataLoading3();
            listBox.Items.Add("DataLoading all complete");
        }

        private async Task DataLoading1()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading1 Complete");
        }

        private async Task DataLoading2()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading2 Complete");
        }

        private async Task DataLoading3()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading3 Complete");
        }

 

 

위와 같이 각 메소드에 Task를 걸고 모두 순차 적으로 awit를 붙여주면 쉽게 처리가 가능하다. 하지만, 이것이 정말 원하는 결과일까? 이렇게 사용하게되면, 최종 메시지가 출력되기 까지 100 + 100 + 100 라는 시간이 필요할 것이다.

 

아래와 같이 수정하도록 하자

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            DataLoding();
        }

        private async void DataLoding()
        {
            listBox.Items.Add("DataLoading...");
            var tasks = new Task[] { DataLoading1(), DataLoading2(), DataLoading3() };
            await Task.WhenAll(tasks);
            listBox.Items.Add("DataLoading all complete");
        }

        private async Task DataLoading1()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading1 Complete");
        }

        private async Task DataLoading2()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading2 Complete");
        }

        private async Task DataLoading3()
        {
            await Task.Delay(100);
            listBox.Items.Add("DataLoading3 Complete");
        }

 

 

위의 문장으로 수정하면, 3개의 Task를 한꺼번에 await 걸어 놓는 것과 같다. WhenAll 이외에도 여러가지 기능들이 있으니 참고하고,

Async, Await를 이용하면 유연한 프로그램을 할 수 있고, 성능개선에도 많은 도움이 된다. 이번 포스트는 여기까지 하고, 소스는 따로 올리지 않겠다.

 

반응형

'Previous Platforms > Samples' 카테고리의 다른 글

HubApp using a dynamic style app development  (0) 2013.08.01
Custom Behavior Sample  (0) 2012.12.25
Text file encoding sample  (0) 2012.11.28
WinRT File Based Database sample  (0) 2012.11.12
Tile + BackgroundTask = LiveTile APP!  (0) 2012.10.30
댓글