C#.NET:Thread

バックグラウンドで処理を実行・中止する方法

using System.Threading;
using System.Windows;

namespace WpfApp
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainWindow()
        {
            // コンポーネントの初期化
            InitializeComponent();

            TxtProcCount.Text = "100";
        }

        // thread
        private Thread _thread = null;

        // threadの制御用
        private ManualResetEvent _event;

        private [[delegate]] void SetProgDelegate(int value);

        /// <summary>
        /// Click Start Button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnStart_Click(object sender, RoutedEventArgs e)
        {
            // threadの中止
            AbortThread(_thread);

            // suspend/resume制御用
            _event = new ManualResetEvent(true);
            SetSuspendResumeButtonTitle();

            // 引数ありのthreadを作成
            _thread = new Thread(new ParameterizedThreadStart(DoProc));

            // バックグラウンドで処理を実行
            _thread.IsBackground = true;

            int maxProcCount;

            if (int.TryParse(TxtProcCount.Text, out maxProcCount))
            {
                PBMain.Minimum = 0;
                PBMain.Maximum = maxProcCount;

                // 引数を渡してthreadを開始
                _thread.Start(maxProcCount);
            }
        }

        /// <summary>
        /// Click Suspend/Resume Button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnSuspendResume_Click(object sender, RoutedEventArgs e)
        {
            if (_event == null)
            {
                return;
            }

            if (_event.WaitOne(0, false))
            {
                // suspend
                _event.Reset();
            }
            else
            {
                // resume
                _event.Set();
            }
            SetSuspendResumeButtonTitle();
        }

        /// <summary>
        /// Click Cancel Button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnCancel_Click(object sender, RoutedEventArgs e)
        {
            AbortThread(_thread);
        }

        /// <summary>
        /// abort thread
        /// </summary>
        /// <param name="thread"></param>
        private void AbortThread(Thread thread)
        {
            if (thread != null)
            {
                thread.Abort();
            }
        }

        /// <summary>
        /// Do Some Process
        /// </summary>
        /// <param name="maxProcCount"></param>
        private void DoProc(object maxProcCount)
        {
            int value = 0;
            SetProg(value);
            while (value < (int)maxProcCount)
            {
                // 100ms間threadを停止
                Thread.Sleep(100);
                value++;
                SetProg(value);

                // ManualResetEventの状態によって処理の一時停止を行う
                _event.WaitOne();
            }
            MessageBox.Show("完了!");
        }

        /// <summary>
        /// set value to progress bar
        /// </summary>
        /// <param name="value"></param>
        private void SetProg(int value)
        {
            if (PBMain.Dispatcher.CheckAccess())
            {
                // プログレスバーにアクセス可能な場合
                PBMain.Value = value;
            }
            else
            {
                // プログレスバーにアクセスできない場合
                PBMain.Dispatcher.Invoke(new SetProgDelegate(SetProg), value);
            }
        }

        /// <summary>
        /// Set Suspend/Resume Button Title
        /// </summary>
        private void SetSuspendResumeButtonTitle()
        {
            string titleStr;
            if (_event.WaitOne(0, false))
            {
                titleStr = "SUSPEND";
            }
            else
            {
                titleStr = "RESUME";
            }
            BtnSuspendResume.Content = titleStr;
        }
    }
}


threadの入れ子
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Controls;

namespace WpfApp
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainWindow()
        {
            // コンポーネントの初期化
            InitializeComponent();

            PB1.Minimum = 0;
            PB1.Maximum = 100;
            PB2.Minimum = 0;
            PB2.Maximum = 100;
            PB3.Minimum = 0;
            PB3.Maximum = 100;
        }

        // thread
        private Thread _thread = null;
        private List<Thread> _threadList = null;

        private delegate void SetProgDelegate(ProgressBar pb, int value);

        /// <summary>
        /// Click Start Button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnStart_Click(object sender, RoutedEventArgs e)
        {
            // threadの中止
            AbortThread(_thread, _threadList);

            // 引数なしのthreadを作成
            _thread = new Thread(new ThreadStart(DoSomething));

            // バックグラウンドで処理を実行
            _thread.IsBackground = true;

            // threadを開始
            _thread.Start();
        }

        /// <summary>
        /// Click Cancel Button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnCancel_Click(object sender, RoutedEventArgs e)
        {
            AbortThread(_thread, _threadList);
        }

        /// <summary>
        /// abort thread
        /// </summary>
        /// <param name="thread"></param>
        private void AbortThread(Thread thread, List<Thread> threadList)
        {
            if (thread != null)
            {
                thread.Abort();
            }
            if (threadList != null)
            {
                foreach (Thread childThread in threadList)
                {
                    AbortThread(childThread, null);
                }
            }
        }

        /// <summary>
        /// Do Some Process
        /// </summary>
        private void DoSomething()
        {
            List<DoProcParam> paramList = new List<DoProcParam>{
                new DoProcParam(PB1, 100, 100),
                new DoProcParam(PB2, 200, 60),
                new DoProcParam(PB3, 150, 30),
            };

            // 引数ありのthreadを作成
            _threadList = new List<Thread>{
                new Thread(new ParameterizedThreadStart(DoProc)),
                new Thread(new ParameterizedThreadStart(DoProc)),
                new Thread(new ParameterizedThreadStart(DoProc)),
            };

            for (int i = 0; i < _threadList.Count; i++)
            {
                // バックグラウンドで処理を実行
                _threadList[i].IsBackground = true;
                // 引数を渡してthreadを開始
                _threadList[i].Start(paramList[i]);
            }

            foreach (Thread thread in _threadList)
            {
                thread.Join();
            }
            MessageBox.Show("完了!");
        }

        /// <summary>
        /// Do Some Process
        /// </summary>
        private void DoProc(object param)
        {
            DoProcParam doProcParam = (DoProcParam)param;
            int value = 0;
            SetProg(doProcParam.ProgressBar, value);
            while (value < doProcParam.MaxValue)
            {
                // ms間threadを停止
                Thread.Sleep(doProcParam.SleepTime);
                value++;
                SetProg(doProcParam.ProgressBar, value);
            }
        }

        /// <summary>
        /// set value to progress bar
        /// </summary>
        /// <param name="pb"></param>
        /// <param name="value"></param>
        private void SetProg(ProgressBar pb, int value)
        {
            if (pb.Dispatcher.CheckAccess())
            {
                // プログレスバーにアクセス可能な場合
                pb.Value = value;
            }
            else
            {
                // プログレスバーにアクセスできない場合
                pb.Dispatcher.Invoke(new SetProgDelegate(SetProg), pb, value);
            }
        }

        /// <summary>
        /// パラメータ用クラス
        /// </summary>
        private class DoProcParam
        {
            public ProgressBar ProgressBar { get; set; }
            public int MaxValue { get; set; }
            public int SleepTime { get; set; }

            public DoProcParam(ProgressBar pb, int maxValue, int sleepTime)
            {
                this.ProgressBar = pb;
                this.MaxValue = maxValue;
                this.SleepTime = sleepTime;
            }
        }

    }
}

最終更新:2014年01月25日 11:09
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。