■ 커스텀 태스크 사용하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


TestAsyncTaskMethodBuilder.cs

 

 

using System;

using System.Runtime.CompilerServices;

 

namespace TestProject

{

    /// <summary>

    /// 테스트 비동기 태스크 메소드 빌더

    /// </summary>

    public struct TestAsyncTaskMethodBuilder

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 비동기 태스크 메소드 빌더

        /// </summary>

        private AsyncTaskMethodBuilder builder;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 태스크 - Task

 

        /// <summary>

        /// 태스크

        /// </summary>

        public TestTask Task

        {

            get

            {

                return new TestTask(this.builder.Task);

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성하기 - Create()

 

        /// <summary>

        /// 생성하기

        /// </summary>

        /// <returns>테스트 비동기 태스크 메소드 빌더</returns>

        public static TestAsyncTaskMethodBuilder Create()

        {

            return new TestAsyncTaskMethodBuilder { builder = AsyncTaskMethodBuilder.Create() };

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 결과 설정하기 - SetResult()

 

        /// <summary>

        /// 결과 설정하기

        /// </summary>

        public void SetResult()

        {

            this.builder.SetResult();

        }

 

        #endregion

        #region 예외 설정하기 - SetException(exception)

 

        /// <summary>

        /// 예외 설정하기

        /// </summary>

        /// <param name="exception">예되</param>

        public void SetException(Exception exception)

        {

            this.builder.SetException(exception);

        }

 

        #endregion

 

        #region 대기 완료시 처리하기 - AwaitOnCompleted<TAwaiter, TStateMachine>(awaiter, stateMachine)

 

        /// <summary>

        /// 대기 완료시 처리하기

        /// </summary>

        /// <typeparam name="TAwaiter">대기자 타입</typeparam>

        /// <typeparam name="TStateMachine">상태 머신 타입</typeparam>

        /// <param name="awaiter">대기자</param>

        /// <param name="stateMachine">상태 머신</param>

        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)

            where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine

        {

            this.builder.AwaitOnCompleted(ref awaiter, ref stateMachine);

        }

 

        #endregion

        #region 비관리 대기 완료시 처리하기 - AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(awaiter, stateMachine)

 

        /// <summary>

        /// 비관리 대기 완료시 처리하기

        /// </summary>

        /// <typeparam name="TAwaiter">대기자 타입</typeparam>

        /// <typeparam name="TStateMachine">상태 머신 타입</typeparam>

        /// <param name="awaiter">대기자</param>

        /// <param name="stateMachine">상태 머신</param>

        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)

            where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine

        {

            this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);

        }

 

        #endregion

        #region 상태 머신 설정하기 - SetStateMachine(stateMachine)

 

        /// <summary>

        /// 상태 머신 설정하기

        /// </summary>

        /// <param name="stateMachine">상태 머신</param>

        public void SetStateMachine(IAsyncStateMachine stateMachine)

        {

            this.builder.SetStateMachine(stateMachine);

        }

 

        #endregion

        #region 시작하기 - Start<TStateMachine>(stateMachine)

 

        /// <summary>

        /// 시작하기

        /// </summary>

        /// <typeparam name="TStateMachine">상태 머신 타입</typeparam>

        /// <param name="stateMachine">상태 머신</param>

        public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine

        {

            this.builder.Start(ref stateMachine);

        }

 

        #endregion

    }

}

 

 

TestTaskAwaiter.cs

 

 

using System;

using System.Runtime.CompilerServices;

 

namespace TestProject

{

    /// <summary>

    /// 테스트 태스크 대기자

    /// </summary>

    public struct TestTaskAwaiter : ICriticalNotifyCompletion, INotifyCompletion

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 태스크

        /// </summary>

        private TestTask task;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 완료 여부 - IsCompleted

 

        /// <summary>

        /// 완료 여부

        /// </summary>

        public bool IsCompleted

        {

            get

            {

                return this.task.IsCompleted;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - TestTaskAwaiter(task)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="task">태스크</param>

        public TestTaskAwaiter(TestTask task)

        {

            this.task = task;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 결과 구하기 - GetResult()

 

        /// <summary>

        /// 결과 구하기

        /// </summary>

        public void GetResult()

        {

        }

 

        #endregion

        #region 완료시 처리하기 - OnCompleted(continuationAction)

 

        /// <summary>

        /// 완료시 처리하기

        /// </summary>

        /// <param name="continuationAction">연결 액션</param>

        public void OnCompleted(Action continuationAction)

        {

            if(this.task.Task == null)

            {

                this.task.AddContinuation(continuationAction);

            }

            else

            {

                this.task.Task.GetAwaiter().OnCompleted(continuationAction);

            }

        }

 

        #endregion

        #region 비관리 완료시 처리하기 - UnsafeOnCompleted(continuationAction)

 

        /// <summary>

        /// 비관리 완료시 처리하기

        /// </summary>

        /// <param name="continuationAction">연결 액션</param>

        public void UnsafeOnCompleted(Action continuationAction)

        {

            if(this.task.Task == null)

            {

                this.task.AddContinuation(continuationAction);

            }

            else

            {

                this.task.Task.GetAwaiter().UnsafeOnCompleted(continuationAction);

            }

        }

 

        #endregion

    }

}

 

 

TestTask.cs

 

 

using System;

using System.Collections.Generic;

using System.Runtime.CompilerServices;

using System.Threading;

using System.Threading.Tasks;

 

namespace TestProject

{

    /// <summary>

    /// 테스트 태스크

    /// </summary>

    [AsyncMethodBuilder(typeof(TestAsyncTaskMethodBuilder))]

    public class TestTask

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 스레드

        /// </summary>

        private Thread thread;

 

        /// <summary>

        /// 태스크

        /// </summary>

        private Task task;

 

        /// <summary>

        /// 완료 여부

        /// </summary>

        private bool isCompleted;

 

        /// <summary>

        /// 연결 액션 리스트

        /// </summary>

        private List<Action> continuationActionList = new List<Action>();

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 태스크 - Task

 

        /// <summary>

        /// 태스크

        /// </summary>

        public Task Task

        {

            get

            {

                return this.task;

            }

        }

 

        #endregion

        #region 완료 여부 - IsCompleted

 

        /// <summary>

        /// 완료 여부

        /// </summary>

        public bool IsCompleted

        {

            get

            {

                if(this.thread == null)

                {

                    return this.task.IsCompleted;

                }

                

                return this.isCompleted;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - TestTask(task)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="task">태스크</param>

        public TestTask(Task task)

        {

            this.task = task;

        }

 

        #endregion

        #region 생성자 - TestTask(action)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="action">액션</param>

        public TestTask(Action action)

        {

            this.thread = new Thread((ThreadStart)(() =>

            {

                action();

 

                this.isCompleted = true;

 

                foreach(Action continuationAction in this.continuationActionList)

                {

                    continuationAction();

                }

            }));

 

            this.thread.Start();

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 연결 추가하기 - AddContinuation(action)

 

        /// <summary>

        /// 연결 추가하기

        /// </summary>

        /// <param name="action">액션</param>

        public void AddContinuation(Action action)

        {

            if(this.thread == null)

            {

                this.task.ContinueWith((t) => { action(); });

            }

            else

            {

                this.continuationActionList.Add(action);

            }

        }

 

        #endregion

        #region 대기자 구하기 - GetAwaiter()

 

        /// <summary>

        /// 대기자 구하기

        /// </summary>

        /// <returns>대기자</returns>

        public TestTaskAwaiter GetAwaiter()

        {

            TestTaskAwaiter awaiter = new TestTaskAwaiter(this);

 

            return awaiter;

        }

 

        #endregion

    }

}

 

 

Program.cs

 

 

using System;

using System.Threading;

using System.Threading.Tasks;

 

namespace TestProject

{

    /// <summary>

    /// 프로그램

    /// </summary>

    class Program

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region 프로그램 시작하기 - Main()

 

        /// <summary>

        /// 프로그램 시작하기

        /// </summary>

        private static void Main()

        {

            Console.Title = "커스텀 태스크 사용하기";

 

            CallAsync();

 

            Console.ReadKey(false);

        }

 

        #endregion

 

        #region 비동기 호출하기 1 - CallAsync1()

 

        /// <summary>

        /// 비동기 호출하기 1

        /// </summary>

        /// <returns>태스크</returns>

        private static async Task CallAsync1()

        {

            await new TaskFactory().StartNew(() =>

            {

                Thread.Sleep(5000);

            });

        }

 

        #endregion

        #region 비동기 호출하기 2 - CallAsync2()

 

        /// <summary>

        /// 비동기 호출하기 2

        /// </summary>

        /// <returns>테스트 태스크</returns>

        private static async TestTask CallAsync2()

        {

            TestTask task = new TestTask(() =>

            {

                Thread.Sleep(5000);

            });

 

            await task;

        }

 

        #endregion

        #region 비동기 호출하기 - CallAsync()

 

        /// <summary>

        /// 비동기 호출하기

        /// </summary>

        private static async void CallAsync()

        {

            await CallAsync1();

 

            Console.WriteLine("비동기 호출 1 완료");

 

            await CallAsync2();

 

            Console.WriteLine("비동기 호출 2 완료");

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요