すらすらプログラマーへのお問い合わせ
すらすらのブログ
アクセス数  累計:000,596,868  昨日:000,000,295  本日:000,000,079
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 ランキング:ゲーム - PS Vita】

前回まで作成したプログラムはプログレスバーを更新するためにタイマーコントロールを使用していましたがこれには理由があります。
直接サブスレッドからプログレスバーの値を変更すればタイマーは必要なくなるのですがそうすると例外は発生してしまいます。
それは、「コントロールはそのハンドルを所有しているスレッドからしか操作できない」という制約があるためです。
Invoke() メソッド
サブスレッドからコントロールを操作するには Invoke() メソッドを使用します。
Invoke() メソッドを使用することによってサブスレッドからメインスレッドのメソッドを呼ぶことができます。そうすることでアクセスの制約を回避することが可能になります。
それではまず Invoke() ためのメソッドを作成します。メソッドを呼ぶためにデリケーターを経由しますので呼び出すメソッドの引数ににあわせてデリゲーターを作成してください。
[VB]
' プログレスバー更新処理用デリゲータ
Delegate Sub delegate_UpdateProgressBar(ByVal value As Integer)

' プログレスバー更新処理
Private Sub UpdateProgressBar(ByVal value As Integer)
    
' プログレスバー更新
    Me.progressBar1.Value = value
End Sub

[C#]
// プログレスバー更新処理用デリゲータ
delegate void delegate_UpdateProgressBar(int value);

// プログレスバー更新処理
private void UpdateProgressBar(int value)
{
    
// プログレスバー更新
    this.progressBar1.Value = value;
}

次にサブスレッドからメインスレッドのコントロールに対して Invoke() メソッドを呼び出します。
[VB]
' プログレスバー更新
Dim callback As delegate_UpdateProgressBar = _
    
New delegate_UpdateProgressBar(AddressOf UpdateProgressBar)

' Invoke してメインスレッドからメソッドを呼び出す
Me.progressBar1.Invoke(callback, _progressValue)

[C#] // プログレスバー更新
delegate_UpdateProgressBar callback =
    
new delegate_UpdateProgressBar(UpdateProgressBar);

// Invoke してメインスレッドからメソッドを呼び出す
this.progressBar1.Invoke(callback, _progressValue);
※Invoke() メソッドで複数の引数を渡す場合には Object 配列を使います。
[VB]
Me.Control.Invoke(callback, New Object() {arg1, arg2, arg3})

[C#]
this.Control.Invoke(callback, new object[]{arg1, arg2, arg3});
フォームの作成
画面は前回とほぼ同じですが、
Timer は必要ありません。

Button:[Button1]
ProgressBar:[ProgressBar1]

VB[Form1.vb]
Imports System.Threading

Public Class Form1

    
Private _progressValue As Integer = 0
    
Private _thread As Thread = Nothing

    Public Sub New()

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

    
End Sub

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

        
If Not _thread Is Nothing Then

            Console.WriteLine(_thread.ThreadState.ToString())

            
' スレッドが停止状態でない場合は終了
            If _thread.ThreadState <> ThreadState.Stopped Then
                Exit Sub
            End If
        End If

        ' スレッド開始
        _thread = New Thread(AddressOf ThreadProc)
        _thread.Start()

    
End Sub

    Private Sub Form1_FormClosed( _
        
ByVal sender As ObjectByVal e As System.Windows.Forms.FormClosedEventArgs) _
        
Handles Me.FormClosed

        
' スレッドを強制終了させる
        _thread.Abort()

        
' メインスレッドに結合する
        _thread.Join()

    
End Sub

    ' スレッド処理
    Private Sub ThreadProc()

        
Try

            For i As Integer = 0 To 10
                
'プログレスの値加算
                _progressValue = i * 10

                
' プログレスバー更新
                Dim callback As delegate_UpdateProgressBar = _
                    
New delegate_UpdateProgressBar(AddressOf UpdateProgressBar)

                
' Invoke してメインスレッドからメソッドを呼び出す
                Me.progressBar1.Invoke(callback, _progressValue)

                Thread.Sleep(1000)
            
Next

        Catch ex As ThreadAbortException
            Console.WriteLine(
"スレッド強制終了!")
        
End Try

    End Sub

    ' プログレスバー更新処理用デリゲータ
    Delegate Sub delegate_UpdateProgressBar(ByVal value As Integer)

    
' プログレスバー更新処理
    Private Sub UpdateProgressBar(ByVal value As Integer)
        
' プログレスバー更新
        Me.progressBar1.Value = value
    
End Sub

End
 Class
C#[Form1.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 Form1 : Form
    {
        
private int _progressValue = 0;
        
private Thread _thread = null;

        
public Form1()
        {
            InitializeComponent();
        }

        
private void button1_Click(object sender, EventArgs e)
        {
            
if (_thread != null)
            {
                
Console.WriteLine(_thread.ThreadState.ToString());

                
// スレッドが停止状態でない場合は終了
                if (_thread.ThreadState != ThreadState.Stopped)
                    
return;
            }

            
// スレッド開始
            _thread = new Thread(ThreadProc);
            _thread.Start();
        }

        
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            
// スレッドを強制終了させる
            _thread.Abort();

            
// メインスレッドに結合する
            _thread.Join();
        }

        
// スレッド処理
        private void ThreadProc()
        {
            
try
            {
                
for (int i = 0; i <= 10; i++)
                {
                    
// プログレスの値加算
                    _progressValue = i * 10;

                    
// プログレスバー更新
                    delegate_UpdateProgressBar callback =
                        
new delegate_UpdateProgressBar(UpdateProgressBar);

                    
// Invoke してメインスレッドからメソッドを呼び出す
                    this.progressBar1.Invoke(callback, _progressValue);

                    
Thread.Sleep(1000);
                }
            }
            
catch (ThreadAbortException ex)
            {
                
Console.WriteLine("スレッド強制終了!");
            }
        }

        
// プログレスバー更新処理用デリゲータ
        delegate void delegate_UpdateProgressBar(int value);

        
// プログレスバー更新処理
        private void UpdateProgressBar(int value)
        {
            
// プログレスバー更新
            this.progressBar1.Value = value;
        }
    }
}
※このページで紹介しているサンプルコードについて管理者は動作保障をいたしません※
※サンプルコードを使用する場合は、自己責任でお願いします※

【楽天 ランキング:スマートフォン】




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

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