■ 대리자의 BeginInvoke/EndInvoke 메소드를 사용해 비동기 호출하기

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


TestProject.zip


MainForm.cs

 

 

using System;

using System.Drawing;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Delegate

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

 

        #region 비트맵 구하기 대리자 - GetBitmapDelegate(sourceBitmap

 

        /// <summary>

        /// 비트맵 구하기 대리자

        /// </summary>

        /// <param name="sourceBitmap">소스 비트맵</param>

        /// <returns>비트맵</returns>

        private delegate Bitmap GetBitmapDelegate(Bitmap sourceBitmap);

 

        #endregion

 

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

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

 

        #region Field

 

        /// <summary>

        /// 소스 비트맵 배열

        /// </summary>

        private Bitmap[] sourceBitmapArray =

        {

            Properties.Resources.sample1,

            Properties.Resources.sample2,

            Properties.Resources.sample3,

            Properties.Resources.sample4

        };

 

        #endregion

 

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

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

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 이벤트를 설정한다.

 

            Load                                   += Form_Load;

            this.resetButton.Click                 += resetButton_Click;

            this.processSynchronouslyButton.Click  += processSynchronouslyButton_Click;

            this.processAsynchronouslyButton.Click += processAsynchronouslyButton_Click;

 

            #endregion

        }

 

        #endregion

 

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

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

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 폼 로드시 처리하기 - Form_Load(sender, e)

 

        /// <summary>

        /// 폼 로드시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Form_Load(object sender, EventArgs e)

        {

            SetSourceBitmap();

        }

 

        #endregion

        #region 다시 설정 버튼 클릭시 처리하기 - resetButton_Click(sender, e)

 

        /// <summary>

        /// 다시 설정 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void resetButton_Click(object sender, EventArgs e)

        {

            SetSourceBitmap();

        }

 

        #endregion

        #region 동기 처리 버튼 클릭시 처리하기 - processSynchronouslyButton_Click(sender, e)

 

        /// <summary>

        /// 동기 처리 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void processSynchronouslyButton_Click(object sender, EventArgs e)

        {

            this.elapsedPeriodLabel.Text = string.Empty;

 

            SetSourceBitmap();

 

            Cursor = Cursors.WaitCursor;

 

            Application.DoEvents();

 

            DateTime startTime = DateTime.Now;

 

            this.pictureBox1.Image = GetBitmap(this.sourceBitmapArray[0]);

 

            this.pictureBox1.Refresh();

 

            this.pictureBox2.Image = GetBitmap(this.sourceBitmapArray[1]);

 

            this.pictureBox2.Refresh();

 

            this.pictureBox3.Image = GetBitmap(this.sourceBitmapArray[2]);

 

            this.pictureBox3.Refresh();

 

            this.pictureBox4.Image = GetBitmap(this.sourceBitmapArray[3]);

 

            this.pictureBox4.Refresh();

 

            DateTime stopTime = DateTime.Now;

 

            TimeSpan elapsedPeriod = stopTime - startTime;

 

            this.elapsedPeriodLabel.Text = elapsedPeriod.TotalSeconds.ToString("0.00") + " 초";

 

            Cursor = Cursors.Default;

        }

 

        #endregion

        #region 비동기 처리 버튼 클릭시 처리하기 - processAsynchronouslyButton_Click(sender, e)

 

        /// <summary>

        /// 비동기 처리 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void processAsynchronouslyButton_Click(object sender, EventArgs e)

        {

            this.elapsedPeriodLabel.Text = string.Empty;

 

            SetSourceBitmap();

 

            Cursor = Cursors.WaitCursor;

 

            Application.DoEvents();

 

            DateTime startTime = DateTime.Now;

 

            Bitmap bitmap1 = (Bitmap)this.sourceBitmapArray[0].Clone();

            Bitmap bitmap2 = (Bitmap)this.sourceBitmapArray[1].Clone();

            Bitmap bitmap3 = (Bitmap)this.sourceBitmapArray[2].Clone();

            Bitmap bitmap4 = (Bitmap)this.sourceBitmapArray[3].Clone();

 

            GetBitmapDelegate getBitmapDelegate = GetBitmap;

 

            IAsyncResult asyncResult1 = getBitmapDelegate.BeginInvoke(bitmap1, null, null);

            IAsyncResult asyncResult2 = getBitmapDelegate.BeginInvoke(bitmap2, null, null);

            IAsyncResult asyncResult3 = getBitmapDelegate.BeginInvoke(bitmap3, null, null);

            IAsyncResult asyncResult4 = getBitmapDelegate.BeginInvoke(bitmap4, null, null);

 

            this.pictureBox1.Image = getBitmapDelegate.EndInvoke(asyncResult1);

            this.pictureBox2.Image = getBitmapDelegate.EndInvoke(asyncResult2);

            this.pictureBox3.Image = getBitmapDelegate.EndInvoke(asyncResult3);

            this.pictureBox4.Image = getBitmapDelegate.EndInvoke(asyncResult4);

 

            DateTime stopTime = DateTime.Now;

 

            TimeSpan elapsedPeriod = stopTime - startTime;

 

            this.elapsedPeriodLabel.Text = elapsedPeriod.TotalSeconds.ToString("0.00") + " 초";

 

            Cursor = Cursors.Default;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 소스 비트맵 설정하기 - SetSourceBitmap()

 

        /// <summary>

        /// 소스 비트맵 설정하기

        /// </summary>

        private void SetSourceBitmap()

        {

            this.pictureBox1.Image = this.sourceBitmapArray[0];

            this.pictureBox2.Image = this.sourceBitmapArray[1];

            this.pictureBox3.Image = this.sourceBitmapArray[2];

            this.pictureBox4.Image = this.sourceBitmapArray[3];

        }

 

        #endregion

        #region 필터 적용하기 - ApplyFilter(sourceBitmap, kernelArray, weight)

 

        /// <summary>

        /// 필터 적용하기

        /// </summary>

        /// <param name="sourceBitmap">소스 비트맵</param>

        /// <param name="kernelArray">커널 배열</param>

        /// <param name="weight">가중치</param>

        /// <returns>비트맵</returns>

        public static Bitmap ApplyFilter(Bitmap sourceBitmap, int[,] kernelArray, int weight)

        {

            Bitmap targetBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);

 

            int kernelWidth  = kernelArray.GetUpperBound(0) + 1;

            int kernelHeight = kernelArray.GetUpperBound(1) + 1;

 

            int halfWidth  = kernelWidth / 2;

            int halfHeight = kernelHeight / 2;

 

            for(int x = halfWidth; x <= sourceBitmap.Width - 1 - halfWidth; x++)

            {

                for(int y = halfHeight; y <= sourceBitmap.Height - 1 - halfHeight; y++)

                {

                    int red   = 0;

                    int green = 0;

                    int blue  = 0;

 

                    for(int dx = 0; dx < kernelWidth; dx++)

                    {

                        for(int dy = 0; dy < kernelHeight; dy++)

                        {

                            Color color = sourceBitmap.GetPixel(x + dx - 1, y + dy - 1);

                            

                            red   += color.R * kernelArray[dx, dy];

                            green += color.G * kernelArray[dx, dy];

                            blue  += color.B * kernelArray[dx, dy];

                        }

                    }

 

                    red   = (int)(127 + red   / weight);

                    green = (int)(127 + green / weight);

                    blue  = (int)(127 + blue  / weight);

 

                    if(red < 0)

                    {

                        red = 0;

                    }

 

                    if(green < 0)

                    {

                        green = 0;

                    }

 

                    if(blue < 0)

                    {

                        blue = 0;

                    }

 

                    if(red > 255)

                    {

                        red = 255;

                    }

 

                    if(green > 255)

                    {

                        green = 255;

                    }

 

                    if(blue > 255)

                    {

                        blue = 255;

                    }

 

                    targetBitmap.SetPixel(x, y, Color.FromArgb(red, green, blue));

                }

            }