すらすらプログラマーへのお問い合わせ
すらすらのブログ
アクセス数  累計:000,125,039  昨日:000,000,099  本日:000,000,061
Loading
スレッド
.NET プログラミング
プロパティグリッド
印刷
リストボックス
スレッド
リストビュー
インストーラー
やってみよう!

できるVisual Studio 2015 Windows /Android/iOS アプリ対応

独習C# 第3版

VisualBasic2013パーフェクトマスター (Perfect Master SERIES)

プログラミング.NET Framework 第4版 (Microsoft Press)

VisualBasic2013逆引き大全555の極意

猫でもわかるWindowsプログラミング 第4版 (猫でもわかるプログラミング)

VisualC#2013逆引き大全555の極意

独自スレッド管理① 最終更新:2010/07/15
【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(MeNew 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(
thisnew 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 ObjectByVal 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;
            }
        }
    }
}
※このページで紹介しているサンプルコードについて管理者は動作保障をいたしません※
※サンプルコードを使用する場合は、自己責任でお願いします※

【楽天 ランキング:パソコン・周辺機器 - パソコンパーツ】


【広告】
  • 【リクナビNEXT】
  • リクナビNEXT
  • リクナビNEXT


  • このサイトはフリーソフトのMerge HTMLで作成されています。
    このサイトはリンクフリーです。

    ページの先頭に戻る Copyright© 2010-2015 Jun.Shiozaki All rights reserved.