すらすらプログラマーへのお問い合わせ
すらすらのブログ
アクセス数  累計:000,610,477  昨日:000,000,153  本日:000,000,007
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の極意

スレッドプール 最終更新:2013/12/15
【Amazon ランキング:本 - コンピュータ・IT】

メイン処理と非同期に動作してくれる便利なスレッドですが、CPUの処理能力には物理的な制限があるため、能力以上の処理をスレッドで並行処理させようとすると高付加状態が続き結果的にシングルスレッドで実行した時よりも遅くなってしまう事があります。
そこで、マルチスレッドで効率的に処理を使うために同時に実行できるスレッド数を制限して負荷が集中しないようにする手法があります。
.NETではそのために ThreadPool クラスが用意されています。

ThreadPool クラスは、要求された処理をすぐには実行せずにいったんプールに貯めておいて FIFO(ファーストイン・ファーストアウト)で順番に処理します。
同時に処理できるスレッド数は SetMaxThreads メソッド指定できるので負荷の高い処理を行う場合は同時実行スレッド数を少なめに設定するとよいでしょう。
スレッドプールへの登録
スレッドプールに処理を登録するには QueueUserWorkItem メソッドを使用します。登録する処理は WaitCallback デリゲーターを使用します。
[VB]
ThreadPool.QueueUserWorkItem( New WaitCallback(AddressOf wk.WorkerProgress))

[C#]
ThreadPool.QueueUserWorkItem(new WaitCallback(wk.WorkerProcess)); 

Object 型の引数も渡すことができます。
[VB]
ThreadPool.QueueUserWorkItem( New WaitCallback(AddressOf wk.WorkerProgress, state))

[C#]
ThreadPool.QueueUserWorkItem(new WaitCallback(wk.WorkerProcess, state)); 


ワーカークラス
QueueUserWorkItem メソッドにはスレッドの実行メソッドと Object 型の引数を渡す方法が用意されていますが、その場合実行部とデータ部が別の場所に存在することになりあまりスマートとはいえません。
そこで私はいつもデータ部と実行部をカプセル化したワーカークラスを作成するようにしています。そうすることで常にデータを処理を一体で管理することができ効率が増します。
VB[WorkerClass.vb]
' スレッドワーカークラス
Public Class WorkerClass

    
Private _status As String = "待機中..."
    Private _progress As Integer = 0

    
' ステータスプロパティ
    Public ReadOnly Property Status() As String
        Get
            Return _status
        
End Get
    End Property

    ' ワーカー処理
    Public Sub WorkerProgress(ByVal state As Object)
        
Try

            For i As Integer = 0 To 100
                _progress = i
                _status = 
String.Format("処理中 {0}%", _progress)
                System.Threading.Thread.Sleep(100)
            
Next

            _status = "処理完了!"

        Catch ex As Exception
            _status = ex.Message
        
End Try
    End Sub

End
 Class
C#[WorkerClass.cs]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ThreadCS
{
    
// スレッドワーカークラス
    public class WorkerClass
    {
        
private string _status = "待機中...";
        
private int _progress = 0;

        
// ステータスプロパティ
        public string Status
        {
            
get { return _status; }
        }

        
// ワーカー処理
        public void WorkerProcess(Object state)
        {
            
try
            {
                
for (int i = 0; i <= 100; i++)
                {
                    _progress = i;
                    _status = 
string.Format("処理中 {0}%", _progress);
                    System.Threading.
Thread.Sleep(100);
                }

                _status = 
"処理完了!";
            }
            
catch (Exception ex)
            {
                _status = ex.Message;
            }
        }
    }
}
フォームの作成
Form2 に ListBox, Button,Timer をはりつけます。
プロパティの内容はすべてデフォルトです。

ListBox:[ListBox1]
Button:[button1]
Timer:[Timer1]

VB[Form2.vb]
Imports System.Threading

Public Class Form2

    
Private _workerList As List(Of WorkerClass)

    
Public Sub New()

        
' この呼び出しは、Windows フォーム デザイナで必要です。
        InitializeComponent()

        
' InitializeComponent() 呼び出しの後で初期化を追加します。

        ' インスタンス作成
        _workerList = New List(Of WorkerClass)

        
' 同時に実行できるスレッド数を指定
        ThreadPool.SetMaxThreads(2, 256)

    
End Sub

    Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        
Handles MyBase.Load

        
' タイマー開始
        Me.timer1.Interval = 500
        
Me.timer1.Start()

    
End Sub

    Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        
Handles button1.Click

        
' ワーカークラス作成してリストに登録
        Dim wk As WorkerClass = New WorkerClass()
        _workerList.Add(wk)

        
' スレッドプールに登録する
        ThreadPool.QueueUserWorkItem( _
            
New WaitCallback(AddressOf wk.WorkerProgress))

    
End Sub


    Private Sub timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        
Handles timer1.Tick

        
Me.timer1.Enabled = False

        Try
            ' ちらつき防止!
            Me.listBox1.BeginUpdate()

            
Dim num As Integer = 1

            
Me.listBox1.Items.Clear()
            
For Each wk As WorkerClass In _workerList
                
' リストボックス追加
                Me.listBox1.Items.Add( _
                    
String.Format("{0:00}:{1}", _
                    num, wk.Status))
                num = num + 1
            
Next

        Finally
            ' ちらつき防止!
            Me.listBox1.EndUpdate()
        
End Try

        Me.timer1.Enabled = True

    End Sub

End
 Class
C#[Form2.cs]
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;
using System.Threading;

namespace ThreadCS
{
    
public partial class Form2 : Form
    {

        
private List<WorkerClass> _workerList = null;

        
public Form2()
        {
            InitializeComponent();

            
// インスタンス作成
            _workerList = _workerList = new List<WorkerClass>();

            
// 同時に実行できるスレッド数を指定
            ThreadPool.SetMaxThreads(2,256); 

        }

        
private void Form2_Load(object sender, EventArgs e)
        {
            
// タイマー開始
            this.timer1.Interval = 500;
            
this.timer1.Start();
        }

        
private void button1_Click(object sender, EventArgs e)
        {
            
// ワーカークラス作成してリストに登録
            WorkerClass wk = new WorkerClass();
            _workerList.Add(wk);

            
// スレッドプールに登録する
            ThreadPool.QueueUserWorkItem(new WaitCallback(wk.WorkerProcess)); 
        }

        
private void timer1_Tick(object sender, EventArgs e)
        {
            
this.timer1.Enabled = false;

            
try
            {
                
// ちらつき防止!
                this.listBox1.BeginUpdate();

                
int num = 1;

                
this.listBox1.Items.Clear();
                
foreach (WorkerClass wk in _workerList)
                {
                    
// リストボックス追加
                    this.listBox1.Items.Add(
                        
string.Format("{0:00}:{1}",
                        num,wk.Status ));
                    num++;
                }
            }
            
finally
            {
                
// ちらつき防止!
                this.listBox1.EndUpdate();
            }

            
this.timer1.Enabled = true;
        }
    }
}
実行
実行すると左のようになります。同時に実行されるスレッドは2つで残りはプールに貯めて実行されるのを待ちます。
※このページで紹介しているサンプルコードについて管理者は動作保障をいたしません※
※サンプルコードを使用する場合は、自己責任でお願いします※

【楽天 ランキング:パソコン・周辺機器 - ネットワーク機器】




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

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