バックグラウンドで処理を実行・中止する方法
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