この知恵ノートを「知恵コレクション」に追加しました。
追加した知恵ノートはMy知恵袋の「知恵コレクション」ページで確認できます。
「知恵コレクション」に登録済みです。
再登録しました。
追加に失敗しました。
ノートに戻り、もう一度やり直してください。
すでに1,000件のノートが登録されています。
新しく追加したい場合は、My知恵袋の「知恵コレクション」ページで登録されているノートを削除してください。
追加できませんでした。
ノートは削除されました。
知恵コレに追加する:1人
C# で作ったスレッドを一時中断したり、強制終了させる方法 第2サンプル 最終ステップ
ライター:abiko_tetuさん(最終更新日時:4日前)投稿日:2012/2/16 アドバイス受付中!
- ナイス!:
23
- 閲覧数:10695
- 付箋(アドバイス)指数普通
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
C# で作ったスレッドを一時中断したり、強制終了させる方法 第2サンプル 最終ステップ
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
「C#でスレッドを作成する方法」における一連の説明(知恵ノート)において、ここでは、「C# で作ったスレッドを一時中断したり、強制終了させる方法 第2サンプル 最終ステップ」について説明します。
総合の目次
本ページを含めた関連事項の総合目次です。
http://note.chiebukuro.yahoo.co.jp/detail/n1729
関連サンプル
<第1サンプル>
http://note.chiebukuro.yahoo.co.jp/detail/n30689
<第2サンプル>
ステップ1(前準備)
http://note.chiebukuro.yahoo.co.jp/detail/n30690
最終ステップ
---> 本サンプル
はじめに
ここでは、Threadクラスで作るスレッドにおいて、その機能を紹介します。
Threadクラスで作るスレッドでは、実行中のスレッドを一時中断させることが可能です。
もちろん、その一時中断しているスレッドを、再開始することも可能です。
また、実行中のスレッドを強制終了させることも可能です(後で再開始はさせないで、そのまま終了)。
なお、そのスレッドの実行中、中断、強制終了の状態を確認する方法も備えています。
他の関連サンプルと比べた特徴
本サンプルでは、スレッドを一時中断中か、否かの状態を、ThreadState プロパティを使って識別させます。
同じく、スレッドを強制終了させた後か、否かの状態も、ThreadState プロパティを使って識別させます。
スレッド終了等の識別方法
スレッドの状態を識別する方法について、以下に説明します。
例えば、スレッドが終了されているか識別したり、スレッドが一時中断されているかを識別する方法です。
識別方法の概要
スレッドの状態を識別する方法は、本サンプルのコードを見ていただけばわかるように、少し複雑になります。
これは、たとえば、スレッドが終了していることを識別したい場合は、スレッドステータスが、Running(スレッド実行中)でない場合に、スレッド終了と判断したいです。
たしかに、状態が Running でない場合は、スレッドは終了している可能性があります。
しかしその一方で、スレッドが中断またはスリープしている可能性もあります。
すなわち、スレッドステータスは、細かくいろいろなケースがあるので、それを考慮して判別を行なう必要があります。
よって、スレッドが終了しているのか判別する場合は、本サンプルのコードのように複雑になります。
スレッド終了の識別だけではなく、スレッド中断の識別も、いろいろなケースを考慮して判別を行なう必要があります。
具体的な手順
具体的な手順としては、まず、スレッドの ThreadState プロパティを使用すると、スレッドのステータスに関する詳細な情報を取得できます。
なお、前述の通り、スレッドは複数の状態を持つことがあるため、ThreadState プロパティに格納されている値は System.Threading.ThreadState 列挙型の値の組み合わせの場合があります。
したがって、スレッド終了などの識別を行ないたいときには、関連するスレッドの状態をすべて入念にチェックする必要があります。
そのスレッドステータスの情報は、下記のマイクロソフトのホームページ(MSDN)と、前回サンプル(上記関連サンプルの<第2サンプル> ステップ1の参照先)でステータスの確認を行なった結果を参考にしています。
ThreadState 列挙体
http://msdn.microsoft.com/ja-jp/library/system.threading.threadstate(v=vs.80).aspx
ThreadStateプロパティでスレッドの状態を調べるには、ビットマスクを使用します。
例えば、スレッドステータスが、Running(スレッド実行中)であることを調べる if 文は、AND演算子を使って、以下のように記述します。
なお、下記はスレッドをThreadObj とした場合です。
if (ThreadObj.ThreadState &
System.Threading.ThreadState.Running != 0)
{
}
ちなみに、「Running(スレッド実行中)ではない」と言う if 文は、以下のように記述します。
if (ThreadObj.ThreadState &
System.Threading.ThreadState.Running == 0)
{
}
スレッドの複数の状態を識別するには、OR演算子を使います。
下記例は、
「スレッドが中断されている」を示しているか、もしくは、
「スレッドの中断の要求処理が行なわれた」を示している場合
におけるif 文です。
if ((ThreadObj.ThreadState &
(System.Threading.ThreadState.Suspended |
System.Threading.ThreadState.SuspendRequested)) != 0)
{
}
サンプルコード
サンプルの内容とソースコードを以下に記述します。
本サンプの仕様
本サンプルでは、スレッド生成等の基本的なコードの書き方を紹介することが目的なので、単純にテキストボックスに文字を表示するだけにしました。
具体的には、「ループで、そのカウンター値を文字列化して表示する」と言う処理をスレッド化しています。
なお、ボタン1は、スレッド開始/終了ボタンです。
また、ボタン2は、スレッド一時中断/再開ボタンです。
すなわち、まだスレッドが作成されていない状態の時に、ボタン1をクリックすると、スレッドが開始します。
逆に、スレッドが実行中の時に、ボタン1をクリックすると、スレッドが強制終了します。
また、スレッドが実行中の時に、ボタン2をクリックすると、スレッドが一時中断します。
逆に、スレッドが一時中断している時に、ボタン2をクリックすると、スレッドが再開始します。
フォームデザイン等の前準備
コードを記述する前に、フォームのデザイン作成などの、以下の前準備を行なって下さい。
<プロジェクトの作成>
本サンプルの確認用に、新規にプロジェクトを作成して下さい。
プロジェクトの種類は、「Windowsフォームアプリケーション」です。
<フォームのデザイン>
デザイン画面で、TextBox (テキストボックス) を1個と、 Button (ボタン)を2個貼り付けて下さい。
<テキストボックスの複数行化>
テキストボックスは、デフォルトでは1行用になっています。
本サンプルでは、複数行の文字を扱いたいので、以下の操作で、テキストボックスを複数行対応にして下さい。
まず、先程貼り付けたテキストボックスを選択状態にして下さい(すなわち、デザイン画面上のテキストボックスをクリックする)。
そうすると、テキストボックスの右上に、小さな三角形のマークが表示されます。
それをクリックすると Multiline と言う表記のチェックボックスが表示されます。
そのチェックボックスにチェックを入れると、複数行対応になります。
あとは、デザイン画面のチェックボックスをマウス操作で、縦幅を広げて下さい。
<イベントプロシージャの作成>
デザイン画面のフォーム(無地の部分)をダブルクリックして、Form1_Load() メソッド を作って下さい。
また、先程貼り付けたデザイン画面上のボタン「button1」をダブルクリックして、button1_Click() メソッド を作って下さい。
同様に、デザイン画面上のボタン「button2」もダブルクリックして、button2_Click() メソッド を作って下さい。
コード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace ControlThreadSample
{
// ************************
// C# で作ったスレッドを一時中断したり、強制終了させる方法
// のサンプルプログラム
//
// --- Thread クラスの ThreadState プロパティで、スレッ
// ドステータスを管理するようにしたもの。
// ************************
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// スレッドからテキストボックスをアクセスすることを指定
Control.CheckForIllegalCrossThreadCalls = false;
}
//============
// メンバー変数
private System.Threading.Thread ThreadMethodThread; // スレッド
//============
// スレッド用メソッド
private void ThreadMethod()
{
// スレッドに行なわせたい処理を記述する。
// ここでは、単純にループ文を行なわせるものとする。
for (int i = 0; i < 1000000000; i++)
{
textBox1.Text += i.ToString() + " ";
System.Threading.Thread.Sleep(1000);
}
}
//============
// フォーム起動時のイベントプロシージャ
private void Form1_Load(object sender, EventArgs e)
{
// 開始/終了ボタン表示内容を初期化
button1.Text = "開始";
// 中断/再開ボタン表示内容を初期化
button2.Text = "一時中断";
// 中断/再開ボタンを無効化
button2.Enabled = false;
}
//============
// スレッド開始/終了ボタン
private void button1_Click(object sender, EventArgs e)
{
// スレッド作成
if (ThreadMethodThread == null) // まだスレッドが生成されていない場合
{
// スレッド作成
// --- 対象処理用メソッドをスレッド用メソッドとして登録
ThreadMethodThread = new System.Threading.Thread(ThreadMethod);
}
// スレッドが既に実行されている場合
// --- スレッドステータス(状態)が、
// 「スレッド上に Thread.Start メソッドを呼び出していない」を示しているか、もしくは、
// 「スレッドを停止している」を示している場合ではない場合
if ((ThreadMethodThread.ThreadState &
(System.Threading.ThreadState.Unstarted |
System.Threading.ThreadState.Stopped)) == 0)
{
// このケースの場合(スレッドが既に実行中の場合)は、本ボタ
// ンの押下は、スレッドを強制終了させる指示を意味している。
// スレッドが中断されている場合
// --- スレッドステータス(状態)が、
// 「スレッドが中断されている」を示しているか、もしくは、
// 「スレッドの中断の要求処理が行なわれた」を示している場合である場合
if ((ThreadMethodThread.ThreadState &
(System.Threading.ThreadState.Suspended |
System.Threading.ThreadState.SuspendRequested)) != 0)
{
// 再開始
// (一時中断中のままで終了させるとエラーになるので再開始させる)
ThreadMethodThread.Resume();
}
// スレッドを強制終了
ThreadMethodThread.Abort();
// もうこのスレッドは使えないので null で初期化
ThreadMethodThread = null;
// 開始/終了ボタン表示内容を切り替え
button1.Text = "開始";
// 中断/再開ボタンを無効化
button2.Enabled = false;
}
// スレッドが終了している場合
else
{
// このケースの場合(スレッドが終了の場合)は、本ボタン
// の押下は、スレッドを開始させる指示を意味している。
// スレッドを開始
ThreadMethodThread.Start();
// 開始/終了ボタン表示内容を切り替え
button1.Text = "終了";
// 中断/再開ボタンを有効化
button2.Enabled = true;
}
}
//============
// スレッド一時中断/再開ボタン
private void button2_Click(object sender, EventArgs e)
{
// スレッドが中断されていない場合
// --- スレッドステータス(状態)が、
// 「スレッドが中断されている」を示しているか、もしくは、
// 「スレッドの中断の要求処理が行なわれた」を示している場合ではない場合
if ((ThreadMethodThread.ThreadState &
(System.Threading.ThreadState.Suspended |
System.Threading.ThreadState.SuspendRequested)) == 0)
{
// このケースの場合(スレッドが中断されていない場合)は、本ボタ
// ンの押下は、スレッドを一時中断させる指示を意味している。
// 一時中断
ThreadMethodThread.Suspend();
// ボタン表示内容を切り替え
button2.Text = "再開";
}
// スレッドが中断されている場合
else
{
// このケースの場合(スレッドが中断されている場合)は、本ボ
// タンの押下は、スレッドを再開させる指示を意味している。
// 再開始
ThreadMethodThread.Resume();
// ボタン表示内容を切り替え
button2.Text = "一時中断";
}
}
private void button3_Click(object sender, EventArgs e)
{
}
}
}
実行結果
ループのカウンターの値が表示されます。
さいごに
本サンプルでは、単純にループで文字を表示するだけです。
よって、本サンプルでは、スレッドにする利点は、あまりありません。
それは、本サンプルが、スレッドの基本を紹介することが主目的だからです。
よって、スレッドにする利点がある応用サンプルを、自分で作って実際に試して見てください。
このノートのライターが設定した関連知恵ノート
アドバイス(このノートのライターへのメッセージ)を送る
このノートはどうでしたか? いいと思ったことや、こうしたらもっとよくなるといったメッセージを送りましょう! ノートの内容やライターについて質問がある場合は、Q&Aから質問してみましょう
アドバイスを送るには、
Yahoo! JAPAN IDでのログインおよび
Yahoo!知恵袋の利用登録が必要です。
このノートに関するQ&A
このノートに関するQ&Aは、まだありません。