첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ GetTextAsyncStateMachine.cs

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace TestProject
{
    /// <summary>
    /// 텍스트 구하기 비동기 상태 머신
    /// </summary>
    public class GetTextAsyncStateMachine : IAsyncStateMachine
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 프로그램
        /// </summary>
        public Program Program;

        /// <summary>
        /// 비동기 태스크 메소드 빌더
        /// </summary>
        public AsyncTaskMethodBuilder<string> Builder;

        /// <summary>
        /// 상태
        /// </summary>
        public int State;

        #endregion

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

        #region Field

        /// <summary>
        /// 태스크 대기자
        /// </summary>
        private TaskAwaiter<string> taskAwaiter;

        /// <summary>
        /// 문자열 태스크
        /// </summary>
        private Task<string> stringTask;

        /// <summary>
        /// 텍스트
        /// </summary>
        private string text;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region (IAsyncStateMachine) 다음으로 이동하기 - MoveNext()

        /// <summary>
        /// 다음으로 이동하기
        /// </summary>
        public void MoveNext()
        {
            try
            {
                TaskAwaiter<string> taskAwaiter;

                switch(State)
                {
                    case 0 :

                        taskAwaiter = this.taskAwaiter;

                        this.taskAwaiter = new TaskAwaiter<string>();

                        State = -1;

                        break;

                    default :

                        this.stringTask = new TaskFactory().StartNew(() => { return "TEST"; });

                        taskAwaiter = this.stringTask.GetAwaiter();

                        if(taskAwaiter.IsCompleted == false)
                        {
                            State = 0;

                            this.taskAwaiter = taskAwaiter;

                            GetTextAsyncStateMachine asyncStateMachine = this;

                            Builder.AwaitUnsafeOnCompleted(ref taskAwaiter, ref asyncStateMachine);

                            return;
                        }

                        break;
                }

                this.text = taskAwaiter.GetResult();
            }
            catch(Exception exception)
            {
                State = -2;

                Builder.SetException(exception);

                return;
            }

            State = -2;

            Builder.SetResult(this.text);
        }

        #endregion
        #region (IAsyncStateMachine) 상태 머신 설정하기 - SetStateMachine(asyncStateMachine)

        /// <summary>
        /// 상태 머신 설정하기
        /// </summary>
        /// <param name="asyncStateMachine">비동기 상태 머신</param>
        public void SetStateMachine(IAsyncStateMachine asyncStateMachine)
        {
        }

        #endregion
    }
}

 

▶ CallAsyncStateMachine.cs

using System;
using System.Runtime.CompilerServices;

namespace TestProject
{
    /// <summary>
    /// 호출하기 비동기 상태 머신
    /// </summary>
    public class CallAsyncStateMachine : IAsyncStateMachine
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 프로그램
        /// </summary>
        public Program Program;

        /// <summary>
        /// 비동기 태스크 메소드 빌더
        /// </summary>
        public AsyncTaskMethodBuilder Builder;

        /// <summary>
        /// 상태
        /// </summary>
        public int State;

        #endregion

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

        #region Field

        /// <summary>
        /// 태스크 대기자
        /// </summary>
        private TaskAwaiter<string> taskAwaiter;

        /// <summary>
        /// 현재 시간
        /// </summary>
        private string currentTime;

        /// <summary>
        /// 텍스트
        /// </summary>
        private string text;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region (IAsyncStateMachine) 다음으로 이동하기 - MoveNext()

        /// <summary>
        /// 다음으로 이동하기
        /// </summary>
        public void MoveNext()
        {
            try
            {
                TaskAwaiter<string> taskAwaiter;

                switch(State)
                {
                    case 0 :

                        taskAwaiter = this.taskAwaiter;

                        this.taskAwaiter = new TaskAwaiter<string>();

                        State = -1;

                        break;

                    default:

                        this.currentTime = DateTime.Now.ToString();

                        taskAwaiter = Program.GetTextAsync().GetAwaiter();

                        if(taskAwaiter.IsCompleted == false)
                        {
                            State = 0;

                            this.taskAwaiter = taskAwaiter;

                            CallAsyncStateMachine callAsyncStateMachine = this;

                            Builder.AwaitUnsafeOnCompleted(ref taskAwaiter, ref callAsyncStateMachine);

                            return;
                        }

                        break;
                }

                this.text = taskAwaiter.GetResult();

                Console.WriteLine(this.currentTime + " : " + this.text);
            }
            catch(Exception exception)
            {
                State = -2;

                Builder.SetException(exception);

                return;
            }

            State = -2;

            Builder.SetResult();
        }

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

        /// <summary>
        /// 상태 머신 설정하기
        /// </summary>
        /// <param name="asyncStateMachine">비동기 상태 머신</param>
        public void SetStateMachine(IAsyncStateMachine asyncStateMachine)
        {
        }

        #endregion
    }
}

 

▶ Program.cs

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace TestProject
{
    /// <summary>
    /// 프로그램
    /// </summary>
    public class Program
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

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

        /// <summary>
        /// 프로그램 시작하기
        /// </summary>
        private static void Main()
        {
            Console.Title = "IAsyncStateMachine 인터페이스 : 비동기 처리하기";

            Program program = new Program();

            Task task = program.CallAsync();

            task.GetAwaiter().GetResult();
        }

        #endregion

        #region 비동기 텍스트 구하기 - GetStringAsync()

        /// <summary>
        /// 비동기 텍스트 구하기
        /// </summary>
        /// <returns>문자열 태스크</returns>
        public Task<string> GetTextAsync()
        {
            GetTextAsyncStateMachine asyncStateMachine = new GetTextAsyncStateMachine
            {
                Program = this,
                Builder = AsyncTaskMethodBuilder<string>.Create(),
                State   = -1
            };

            asyncStateMachine.Builder.Start(ref asyncStateMachine);

            return asyncStateMachine.Builder.Task;
        }

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

        /// <summary>
        /// 비동기 호출하기
        /// </summary>
        /// <returns>태스크</returns>
        public Task CallAsync()
        {
            CallAsyncStateMachine asyncStateMachine = new CallAsyncStateMachine
            {
                Program = this,
                Builder = AsyncTaskMethodBuilder.Create(),
                State   = -1
            };

            asyncStateMachine.Builder.Start(ref asyncStateMachine);

            return asyncStateMachine.Builder.Task;
        }

        #endregion
    }
}
728x90
반응형
그리드형
Posted by 사용자 icodebroker

댓글을 달아 주세요