PROGRAMING/C#

Background worker - Test project with WPF

파란실버라이트 2017. 2. 16. 10:41

Head Frist c# 3rd Edition에 부록에 있는 Background worker 구현 (Progress bar update)

- Do work process

- Cancellation process

- report progress  


1. 쓰레드로 구현하지 않을 경우 , Progress bar가 진행하는 동안 Main process를 접근 불가 (check를 하지 않고 실행)

2. 쓰레드와 Time.Sleep을 구현하는 방법 보다 간단함 




[MainWindow.xml]

<Window x:Class="BackgroundWorkerTest.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:BackgroundWorkerTest"

        mc:Ignorable="d"

        Title="Background Worker Example" Height="150" Width="300">

    <Grid>

        <Grid.RowDefinitions>

            <RowDefinition Height="*"></RowDefinition>

            <RowDefinition Height="*"></RowDefinition>

            <RowDefinition Height="*"></RowDefinition>

        </Grid.RowDefinitions>


        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="*"></ColumnDefinition>

            <ColumnDefinition Width="*"></ColumnDefinition>

            <ColumnDefinition Width="*"></ColumnDefinition>

        </Grid.ColumnDefinitions>


        <CheckBox Name="useBackgroundWorkerCheckbox"  Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center"></CheckBox>

        <Label Grid.Column="1" Grid.ColumnSpan="2" Content="Use BackgroundWoker" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>

        <Button  Name="goButton" Grid.Row="1" Grid.Column="0" Margin="3,3,3,3" Content="Go!" FontSize="10.667" Click="goButton_Click" IsEnabled="True"></Button>

        <Button  Name="cancelButton" Grid.Row="1" Grid.Column="1" Margin="3,3,3,3" Content="Cancel" FontSize="10.667" Click="cancelButton_Click" IsEnabled="True"  ></Button>

        <ProgressBar Grid.Row="2" Margin="3,3,3,3" Grid.ColumnSpan="3" Name="progressBar1"></ProgressBar>


        


    </Grid>

</Window>


[MainWindow.xaml.cs]

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;


namespace BackgroundWorkerTest

{

    /// <summary>

    /// Interaction logic for MainWindow.xaml

    /// </summary>

    public partial class MainWindow : Window

    {

        private readonly BackgroundWorker backgroundWorker1 = new BackgroundWorker();


        public MainWindow()

        {

            InitializeComponent();

            backgroundWorker1.WorkerSupportsCancellation = true;

            backgroundWorker1.WorkerReportsProgress = true;

            backgroundWorker1.DoWork += backgroundWorker1_DoWork;

            backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;

            backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;

        }


        //ui event

        private void goButton_Click(object sender, EventArgs e)

        {

            goButton.IsEnabled = false;


            if (!useBackgroundWorkerCheckbox.IsChecked == true)

            {

                // If we're not using the background worker, just start wasting CPU cycles

                for (int i = 1; i <= 100; i++)

                {

                    WasteCPUCycles();

                    progressBar1.Value = i;

                }

                goButton.IsEnabled = true;

            }

            else {

                // If the form's using the background worker, it enables the Cancel button.

                cancelButton.IsEnabled = true;


                // If we are using the background worker, use its RunWorkerAsync()

                // to tell it to start its work

                backgroundWorker1.RunWorkerAsync(new Guy("Bob", 37, 146));

            }

        }

        /// <summary>

        /// When the user clicks Cancel, call BackgroundWorker.CancelAsync() to send it a cancel message

        /// </summary>

        private void cancelButton_Click(object sender, EventArgs e)

        {

            // If the user clicks Cancel, it calls the BackgroundWorker's CancelAsync()

            // method to give it the message to cancel.

            backgroundWorker1.CancelAsync();

        }


        //background worker function

        /// <summary>

        /// The BackgroundWorker object runs its DoWork event handler in the background

        /// </summary>

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

        {

            // The e.Argument property returns the argument that was passed to RunWorkerAsync()

            Console.WriteLine("Background worker argument: " + (e.Argument ?? "null"));


            // Start wasting CPU cycles

            for (int i = 1; i <= 100; i++)

            {

                WasteCPUCycles();

                // Use the BackgroundWorker.ReportProgress method to report the % complete

                backgroundWorker1.ReportProgress(i);


                // If the BackgroundWorker.CancellationPending property is true, cancel

                if (backgroundWorker1.CancellationPending)

                {

                    Console.WriteLine("Cancelled");

                    break;

                }

            }

        }

        /// <summary>

        /// BackgroundWorker fires its ProgressChanged event when the worker thread reports progress

        /// </summary>

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)

        {

            progressBar1.Value = e.ProgressPercentage;

        }

        /// <summary>

        /// BackgroundWorker fires its RunWorkerCompleted event when its work is done (or cancelled)

        /// </summary>

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

        {

            // When the work is complete, the RunWorkerCompleted event handler 

            // re-enables the Go! button and disables the Cancel button.

            goButton.IsEnabled = true;

            cancelButton.IsEnabled = false;

        }


        //other function

        /// <summary>

        /// Waste CPU cycles causing the program to slow down by doing calculations for 100ms

        /// </summary>

        private void WasteCPUCycles()

        {

            DateTime startTime = DateTime.Now;

            double value = Math.E;

            while (DateTime.Now < startTime.AddMilliseconds(100))

            {

                value /= Math.PI;

                value *= Math.Sqrt(2);

            }

        }

        /// <summary>

        /// Clicking the Go button starts wasting CPU cycles for 10 seconds

        /// </summary>




    }

}


- 아래 프로젝트(Viaual studio 2015에서 작성)

BackgroundWorkerTest.7z

- 실행 파일 

Release.7z