アクセス数 累計:000,125,039 昨日:000,000,099 本日:000,000,061
|
|
|
|
【Amazon ランキング:ゲーム - プレイステーション4】
|
前回 ThreadPool クラスについて説明しましたが、簡単に使える反面、内部がブラックボックス化されていて拡張性に欠けるのが難点です。それならば自分で作ってしまえということで、ここまで勉強したことを応用して独自のスレッド管理クラスを作ってみようと思います。
今回は、スレッドの実行部分のワーカークラスとスレッドを管理する管理クラスの2つを作って見ましょう。
|
ワーカーベースクラス |
このワーカーベースクラスはこのクラス自体ではインスタンスかできない抽象クラスです。このクラスをベースに実際の処理を行うワーカクラスを作成していきます。
Priority プロパティでスレッドの優先順位を指定することができます |
VB[WorkerBaseClass.vb] |
Imports System.Threading
Public MustInherit Class WorkerBaseClass : Implements IDisposable
'イベント定義
Public Event WorkerThreadEndEvent As EventHandler
' ワーカーのステータス
Public Enum worker_status
Standby ' 待機中
Running ' 実行中
[End] ' 終了
Aborted ' 強制終了
[Error] ' エラー終了
End Enum
' スレッドID(未実行時は0)
Private _ThreadID As ULong
' ワーカーステータス
Private _workerStatus As worker_status
' スレッド
Private _th As Thread = Nothing
' 優先順位
Private _priority As ThreadPriority
' コンストラクタ
Public Sub New()
_workerStatus = worker_status.Standby
_priority = ThreadPriority.Normal
_ThreadID = 0
End Sub
' スレッドID
Public ReadOnly Property ThreadID() As ULong
Get
Return _ThreadID
End Get
End Property
' ワーカーステータスプロパティ
Public ReadOnly Property WorkerStatus() As worker_status
Get
Return _workerStatus
End Get
End Property
' 優先順位プロパティ
Public Property Priority()
Get
Return _priority
End Get
Set(ByVal value)
_priority = value
End Set
End Property
' 処理スタート
Public Sub Start(ByVal threadID As ULong)
' スレッドID
_ThreadID = threadID
' スレッド作成
_th = New Thread(AddressOf ThreadProc)
' 優先順位
_th.Priority = _priority
' スレッド開始
_th.Start()
End Sub
' 強制終了
Public Sub Abort()
If _th Is Nothing Then
_workerStatus = worker_status.Aborted
Return
End If
Select Case _th.ThreadState
Case ThreadState.Running, _
ThreadState.WaitSleepJoin, _
ThreadState.Suspended, _
ThreadState.SuspendRequested
_th.Abort()
_th.Join(1000)
Case ThreadState.AbortRequested
_th.Join(1000)
Case ThreadState.Aborted
Case ThreadState.Stopped
Case ThreadState.Unstarted
End Select
_th = Nothing
End Sub
Private Sub ThreadProc()
Try
' 処理開始
_workerStatus = worker_status.Running
' ワーカープロセス実行
WorkerProcess()
' 処理終了
_workerStatus = worker_status.End
Catch ex As ThreadAbortException
' 強制終了
_workerStatus = worker_status.Aborted
Console.WriteLine(ex.ToString())
Catch ex As Exception
' エラー終了
_workerStatus = worker_status.Error
Console.WriteLine(ex.ToString())
End Try
' スレッド終了イベント送信
RaiseEvent WorkerThreadEndEvent(Me, New EventArgs())
End Sub
' ワーカープロセス
' 抽象メソッドなので実態は継承先で記述します。
Protected MustOverride Sub WorkerProcess()
' Dispose サポート
Private disposedValue As Boolean = False
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
Me.Abort()
End If
End If
Me.disposedValue = True
End Sub
End Class
|
|
C#[WorkerBaseClass.cs] |
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ThreadCS
{
// ワーカーベースクラス
// このクラスは抽象クラスです。継承して使用します。
public abstract class WorkerBaseClass : IDisposable
{
// イベント定義
public event EventHandler WorkerThreadEndEvent = null;
// ワーカーのステータス
public enum worker_status
{
Standby, // 待機中
Running, // 実行中
End, // 終了
Aborted, // 強制終了
Error // エラー終了
}
// スレッドID(未実行時は0)
private ulong _ThreadID;
// ワーカーステータス
private worker_status _workerStatus;
// スレッド
private Thread _th = null;
// 優先順位
private ThreadPriority _priority;
// コンストラクタ
public WorkerBaseClass()
{
_workerStatus = worker_status.Standby;
_priority = ThreadPriority.Normal;
_ThreadID = 0;
}
// スレッドID
public ulong ThreadID
{
get { return _ThreadID; }
}
// ワーカーステータスプロパティ
public worker_status WorkerStatus
{
get { return _workerStatus; }
}
// 順位プロパティ
public ThreadPriority Priority
{
get { return _priority; }
set { _priority = value; }
}
// 処理スタート
public void Start(ulong threadID)
{
// スレッドID
_ThreadID = threadID;
// スレッド作成
_th = new Thread(ThreadProc);
// 優先順位
_th.Priority = _priority;
// スレッド開始
_th.Start();
}
// 強制終了
public void Abort()
{
if (_th == null)
{
_workerStatus = worker_status.Aborted;
return;
}
switch( _th.ThreadState ){
case ThreadState.Running:
case ThreadState.WaitSleepJoin:
case ThreadState.Suspended:
case ThreadState.SuspendRequested:
_th.Abort();
_th.Join(1000);
break;
case ThreadState.AbortRequested:
_th.Join(1000);
break;
case ThreadState.Aborted:
case ThreadState.Stopped:
case ThreadState.Unstarted:
break;
}
_th = null;
}
// スレッド処理
private void ThreadProc()
{
try
{
// 処理開始
_workerStatus = worker_status.Running;
// ワーカープロセス実行
WorkerProcess();
// 処理終了
_workerStatus = worker_status.End;
}
catch (ThreadAbortException ex)
{
// 強制終了
_workerStatus = worker_status.Aborted;
Console.WriteLine(ex.ToString());
}
catch (Exception ex)
{
// エラー終了
_workerStatus = worker_status.Error;
Console.WriteLine(ex.ToString());
}
// スレッド終了イベント送信
if (WorkerThreadEndEvent != null)
WorkerThreadEndEvent(this, new EventArgs());
}
// ワーカープロセス
// 抽象メソッドなので実態は継承先で記述します。
protected abstract void WorkerProcess();
// Dispose サポート
private bool _disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
this.Abort();
}
_disposed = true;
}
}
}
}
|
|
スレッド管理クラス |
ワーカースレッドを管理するクラスです。ThreadPool クラスと同様の機能を備えています。Abort() メソッドですべての処理を強制終了することができます。 |
VB[ThreadManager.vb] |
' スレッドマネージャークラス
Public Class ThreadManager : Implements IDisposable
' 最大ワーカースレッド数
Private _maxWorkerThreadCount As Integer
' ワーカースレッド
Private _workerList As List(Of WorkerBaseClass)
' スレッドID
Private maxThreadID As ULong
' コンストラクタ
Public Sub New()
_maxWorkerThreadCount = 2
_workerList = New List(Of WorkerBaseClass)()
maxThreadID = 1
End Sub
' ワーカースレッド追加処理
Public Sub AddWorkerThread(ByVal wk As WorkerBaseClass)
' リストの追加
_workerList.Add(wk)
' 次のスレッドを開始する
StartNextThread()
End Sub
' 強制終了処理
Public Sub Abort()
' ワーカースレッドを強制終了させる
For Each wk As WorkerBaseClass In _workerList
wk.Abort()
wk.Dispose()
Next
End Sub
Private Sub StartNextThread()
Dim cnt As Integer = 0
SyncLock (_workerList)
' 待機中のスレッドを検索
For Each wk As WorkerBaseClass In _workerList
Select Case wk.WorkerStatus
Case WorkerBaseClass.worker_status.Running
cnt = cnt + 1
Case WorkerBaseClass.worker_status.Standby
' イベントをハンドリングしてスレッド実行
AddHandler wk.WorkerThreadEndEvent, AddressOf WorkerThreadEndEvent
wk.Start(maxThreadID)
'オーバーフロー防止
If maxThreadID >= ULong.MaxValue Then
maxThreadID = 0
End If
maxThreadID = maxThreadID + 1
Exit Sub
Case Else
End Select
' 最大ワーカースレッド数に達している
If cnt >= _maxWorkerThreadCount Then
Return
End If
Next
End SyncLock
End Sub
' ワーカースレッド終了イベント
Private Sub WorkerThreadEndEvent(ByVal sender As Object, ByVal e As EventArgs)
Dim wkEnd As WorkerBaseClass = CType(sender, WorkerBaseClass)
SyncLock (_workerList)
' ワーカークラスをリストから削除する
For Each wk As WorkerBaseClass In _workerList
If wkEnd.ThreadID = wk.ThreadID Then
_workerList.Remove(wk)
Exit For
End If
Next
End SyncLock
' 次のスレッドを開始する
StartNextThread()
End Sub
' 最大ワーカースレッド数プロパティ
Public Property MaxWorkerThreadCount()
Get
Return _maxWorkerThreadCount
End Get
Set(ByVal value)
_maxWorkerThreadCount = value
End Set
End Property
' Dispose サポート
Private disposedValue As Boolean = False
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
Me.Abort()
End If
End If
Me.disposedValue = True
End Sub
End Class
|
|
C#[ThreadManager.cs] |
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ThreadCS
{
// スレッドマネージャークラス
public class ThreadManager : IDisposable
{
// 最大ワーカースレッド数
private int _maxWorkerThreadCount;
// ワーカースレッド
private List<WorkerBaseClass> _workerList;
// スレッドID
private ulong maxThreadID;
// コンストラクタ
public ThreadManager()
{
_maxWorkerThreadCount = 2;
_workerList = new List<WorkerBaseClass>();
maxThreadID = 1;
}
// 最大ワーカースレッド数プロパティ
public int MaxWorkerThreadCount
{
get { return MaxWorkerThreadCount; }
set { _maxWorkerThreadCount = value; }
}
// ワーカースレッド追加処理
public void AddWorkerThread( WorkerBaseClass wk ){
// リストの追加
_workerList.Add(wk);
// 次のスレッドを開始する
StartNextThread();
}
// 強制終了処理
public void Abort()
{
// ワーカースレッドを強制終了させる
foreach (WorkerBaseClass wk in _workerList)
{
wk.Abort();
wk.Dispose();
}
// リストクリア
_workerList.Clear();
}
// 次のスレッド開始
private void StartNextThread()
{
int cnt = 0;
lock (_workerList)
{
// 待機中のスレッドを検索
foreach (WorkerBaseClass wk in _workerList)
{
switch (wk.WorkerStatus)
{
case WorkerBaseClass.worker_status.Running:
cnt++;
break;
case WorkerBaseClass.worker_status.Standby:
// イベントをハンドリングしてスレッド実行
wk.WorkerThreadEndEvent += new EventHandler(WorkerThreadEndEvent);
wk.Start(maxThreadID);
// オーバーフロー防止
if (maxThreadID >= ulong.MaxValue)
maxThreadID = 0;
maxThreadID++;
return;
default:
break;
}
// 最大ワーカースレッド数に達している
if (cnt >= _maxWorkerThreadCount)
return;
}
}
}
// ワーカースレッド終了イベント
private void WorkerThreadEndEvent(object sender, EventArgs e)
{
WorkerBaseClass wkEnd = (WorkerBaseClass)sender;
lock (_workerList)
{
// ワーカークラスをリストから削除する
foreach (WorkerBaseClass wk in _workerList)
{
if (wkEnd.ThreadID == wk.ThreadID)
{
_workerList.Remove(wk);
break;
}
}
}
// 次のスレッドを開始する
StartNextThread();
}
// Dispose サポート
private bool _disposed = false;
public void Dispose()
{
Dispose(true);
}
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
this.Abort();
}
_workerList = null;
_disposed = true;
}
}
}
}
|
|
|
※このページで紹介しているサンプルコードについて管理者は動作保障をいたしません※
※サンプルコードを使用する場合は、自己責任でお願いします※
|
【楽天 ランキング:パソコン・周辺機器 - パソコンパーツ】
|
|
|
|
このサイトはフリーソフトのMerge HTMLで作成されています。
このサイトはリンクフリーです。
|
ページの先頭に戻る |
Copyright© 2010-2015 Jun.Shiozaki All rights reserved. |
|
|
|