画像ファイル
画像ファイル マルチスレッド入門
VB.NET C#全般
1羊の皮を着た狼 VB.NET
2Form1、Form2の相互参照
3Form1、Form2の相互参照 2
4VB.NET C# データ型の基本
5VB.NET C# 文字列
6VB.NET タイマー精度
7BackgroundWorkerの魅力1..
8BackgroundWorkerの魅力2..
9VB6のタイマー
10コントロールの配列をインデクサ..
11コントロールの配列はジェネリク..
12インデクサ(C#、VB.NET)
13インデクサでBit操作
14Unicode 入門
15デリゲート入門
16マルチスレッド入門
17イベント入門
18デリゲートとイベント
18インターフェースの基本

RichTextBox関係
1RichTextBoxの不思議
2テキスト色付け高速化計画
3VB.NET RichTextBox1
4VB.NET RichTextBox 2

RS-232C関係
1RS-232Cの基礎
2RS-232Cの何が変わった..
3SerialPortクラス
4Unicode(ユニコード)の壁
5マルチスレッドの壁
6RS-232C サンプルコード
7RS-232CのHEXモニタ
8RS-232C 送信モジュール
9RS-232Cのループテスト
10RS-232Cのピンチェンジ..

Socket通信
1C#、VB2005 でSocket通信
2サーバー 複数接続

プロセス間通信
1プロセス間通信(送信側)
2プロセス間通信(受信側)


質問、意見はこちらに
画像ファイル

マルチスレッドとは何か、セカンドスレッドからメインスレッドを操作する
マルチスレッドとは並列処理です。
CLR(Common Language Runtime)は簡単にマルチスレッドを実現するクラスを持っています。
Streamクラスなどはマルチスレッド使用して、ファイルの書き込みや読み出しを効率よく行ないます。
殆どの場合は明示的に複数のスレッドを管理する必要は有りませんが、一部のクラスはマルチスレッド の管理が不可欠となります。
例えばストップ・ウオッチをマルチスレッドで作成して、カウントはセカンドスレッドで、表示をメインスレッドで 行なう場合は、スレッドを意識したコーディングが必要になります。
またRS−232CのComイベントはセカンドスレッドで発生します、この為セカンドスレッドで取得した データをメインスレッドで表示したい場合や、ピンチェンジをメインスレッドで表示したい場合は、 マルチスレッド理解する必要が有ります。
ここでは最初に直面するマルチスレッドの問題点に焦点を絞って説明します。
(以下のマルチスレッドの説明にはデリゲートの理解が必要です、デリゲートについては 「デリゲート入門」 をお読み下さい。)

試しに、簡単なマルチスレッドのコードを作成してみましょう。
先ずフォームにラベルを一つ貼り付けます。
続いてボタンを2つ貼り付けます。
1番目のボタンを押すと、ラベルに現在の時間が表示されます。
2番目のボタンを押すと、第2スレッドを作成して第2スレッドからラベルに時間を表示します。
2番目のボタンクリックイベントの中で第2スレッドを作成するコードは以下のようになります。
C#のコード
Thread t1 = new Thread(new ThreadStart(setTime ));
VB.NETのコード
Dim t1 As Thread = New Thread(New ThreadStart(AddressOf SetTime))

このコードはスレッドクラスのインスタンスを作成しています。
nwe Tread(New Tread).....はコンストラクタです。
コンストラクタの引数
C#のコード
new ThreadStart(setTime ); 
VB.NETのコード
New ThreadStart(AddressOf SetTime)
これは何でしょうか?
実はこれはdelegateです、Threadコンストラクタはdelegate型の引数と一つ取ります。
この引数にはCLR(Common Language Runtime)にあるThreadStartデリゲートを使用しています。
ちなみにThreadStartデリゲートはCLRの中で
C#のコード
public delegate void TreadStart();
VB.NETのコード
Public  Delegate Sub TreadStart()
と定義されています。
TreadStartデリゲートに登録されるメソドはスレッドで実行したいsetTime(SetTime)メソドです。

さてスレッドのインスタンスを作成しただけでは、スレッドはスタートしません。
スレッドの実行をスタートさせる為にはTreadクラスのStartメソドを呼び出します。
C#のコード
t1.Start();
VB.NETのコード
t1.Start()
これで第2スレッドがスタートしました。
問題はこれからです。
第2スレッドの中からデリゲートで呼び出されるメソドのsetTimeの中に DisplayTime()というメソド しか無かったとします、このメソドはlabel1(Label1)のtext(Text)に文字列を設定するものです。
この場合以下のエラーが表示されます。

画像ファイル

マルチスレッドの場合、メインスレッド以外のスレッドからメインスレッドにあるコントロールにアクセス しようとするとアクセスが拒否されるのです。
ではマルチスレッドの場合メインスレッド以外からメインスレッドのコントロールにアクセスできないのでしょうか?
答えは「出来る」です、
C#のコード
Invoke(new MyDelegate(DisplayTime)); 
VB.NETのコード
Invoke(New MyDelegate(AddressOf DisplayTime))
メイン以外のスレッドからメインスレッドのコントロールにアクセスする場合は、Invokeを使用します。
このInvokeはControl.Invokeと言われるもので、デリゲートを引数に取り、引数のデリゲートの実行を コントロールの有るメインのスレッドで行なうものです。
InvokeはFormが持つメソドであり、次の様に書き換えられます。
C#のコード
this.Invoke(new MyDelegate(DisplayTime));
VB.NETのコード
Me.Invoke(New MyDelegate(AddressOf DisplayTime))
又、label(Label)やbutton(Button)と言ったコントロールもFormから派生したものですので、当然 Invokeメソドを継承しています。
従って、
C#のコード
label1.Invoke(new MyDelegate(DisplayTime));
VB.NETのコード
Label1.Invoke(New MyDelegate(AddressOf DisplayTime))
C#のコード
button1.Invoke(new MyDelegate(DisplayTime));
VB.NETのコード
Button1.Invoke(New MyDelegate(AddressOf DisplayTime))
も可能で実行結果は同じになります。
さてsetTime(SetTime)メソドはボタン1を押した時にも呼び出されます。
ボタン1を押した時は通常のメインスレッドからの呼び出しとなり、Invokeメソドを 使う必要は有りません、そこでInvokeメソドが必要か否かを判断する、 InvokeRequiredと言うメソドがあり、Invokeが必要なときはtrue(True)を返します。
C#のコード
if (InvokeRequired)
VB.NETのコード
If InvokeRequired Then
このコードはInvokeが必要か否か、すなわちメソドがメインスレッドから呼び出されたのか、 又はメインスレッド以外から呼び出されたかを判断して処理を行ないます。

どうでしょう、初めての方は難しかったかも知れません、以下まとめて置きます。
  •  マルチスレッドは、ThreadingのTreadクラスを使用する。
  •  TreadクラスのコンストラクタはTreadStartデリゲートを引数に取る。
  •  TreadStartデリゲートにはスレッドで実行したいメソドを登録する。
  •  Treadを実行するにはTrearクラスのStartメソドを呼び出す。
  •  メインスレッド以外からメインスレッドのコントロールにアクセスする場合はControl.Invokeを使用する。
  •  Invokeメソドはデリゲートを引数に取り、其のデリゲートには実行したいメソドを登録する。

サンプルコード
C#、VB.NETともに、フォームに label1(Label1)とbutton1(Button1)を貼り付ける。
C#のコード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace MulutiTread
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

//デリゲートそ宣言する
delegate void MyDelegate();

public void setTime()
{
//Invokeが必要な時はInvokeを使い、不必要の時は直接書き込む
if (InvokeRequired)
Invoke(new MyDelegate(DisplayTime));
else
DisplayTime();
}

void DisplayTime()
{
//現在の時刻を表示する
label1.Text = DateTime.Now.ToString();
}

private void button1_Click(object sender, EventArgs e)
{
//メインスレッドから表示
setTime();
}

private void button2_Click(object sender, EventArgs e)
{
//第2スレッドから表示
Thread t1 = new Thread(new ThreadStart(setTime ));
t1.Start();
}
}
}

         
VB.NETのコード
Option Strict On
Imports System.Threading
Public Class Form1
'デリゲートの宣言
Delegate Sub MyDelegate()

'時間を書き込む関数
Private Sub SetTime()
If InvokeRequired Then
'Invokeが必要な場合はInvokeで書き込む
Invoke(New MyDelegate(AddressOf DisplayTime))
Else
DisplayTime()
End If
End Sub

Private Sub DisplayTime()
'実際に書き込む
Label1.Text = DateTime.Now.ToString()
End Sub

'メインスレッドから書き込む
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal
e As System.EventArgs) Handles Button1.Click
SetTime()
End Sub

'セカンドスレッドから書き込む
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
'新しいスレッドを作成して書き込む
Dim t1 As Thread = New Thread(New ThreadStart(AddressOf SetTime))
t1.Start()
End Sub
End Class

画像ファイル