アクセス数 累計:000,125,041 昨日:000,000,099 本日:000,000,063
|
|
|
|
【Amazon ランキング:ゲーム - Wii U】
|
|
メイン処理と非同期に動作してくれる便利なスレッドですが、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. |
|
|
|