すらすらプログラマーへのお問い合わせ
すらすらのブログ
アクセス数  累計: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 ランキング:DVD - アニメ】

前の回で作成したスレッドプログラムで多重起動は防止できるようになったと思いますがデバッグモードで実行している時に画面が閉じているのにまだ実行されているという現象は発生しなかったでしょうか?
スレッドを開始してプログレスバーが動いている途中で画面を閉じるとその現象が発生するのですが、その理由は左図の通りです。
メインスレッドから起動されたサブスレッドは画面が閉じても動き続けていて、アプリケーションはサブスレッドが終了するまで動き続けるからです。
スレッドプログラミングをするにあたりこのような状態が発生すること常に意識しておかないと画面を閉じたにプロセスが生きたままになっていて思わぬ障害を引き起こしかねません。
この回ではこのような状態を回避する方法を解説したいと思います。
Abort() と Join()
画面を閉じた時にアプリケーションを終了させるにはまずサブスレッドを停止させる必要があります。それを行うのが Thread.Abort() メソッドです。
メインスレッドからサブスレッドに対して Abort() を要求するとサブスレッド側は ThreadAbortException を発生させてサブスレッド処理を強制的の停止させます。ですので、サブスレッド側では Try~Catch セクションで ThreadAbortException をキャッチしてスレッドが中断した際の適切な処理を行ってください。
[VB]
' スレッドを強制終了させる
_thread.Abort()

[C#]
// スレッドを強制終了させる
_thread.Abort();
メインスレッドで Abort() を呼び出したあとはサブスレッドが終了するまで Join() メソッドで待機します。
Join() メソッドを呼ぶとサブメソッドが終了するまでメインスレッドは待ち状態なり、解除された時にはサブスレッドは完全に停止しているということになり完全に同期がとれます。
[VB]
' メインスレッドに結合する
_thread.Join()

[C#]
// メインスレッドに結合する
_thread.Join();
フォームの作成
画面は前回と同じです。
Form1 に Button, ProgressBar,Timer をはりつけます。
プロパティの内容はすべてデフォルトです。

Button:[Button1]
ProgressBar:[ProgressBar1]
Timer:[Timer1]


VB[Form1.vb]
Imports System.Threading

Public Class Form1

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

    Public Sub New()

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

        
' プログレスバー更新タイマー開始
        timer1.Interval = 200
        timer1.Enabled = 
True

    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

        
If Not _thread Is Nothing Then
            ' スレッドを強制終了させる
            _thread.Abort()

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

    End Sub

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

        
Try

            For i As Integer = 0 To 10
                
'プログレスの値加算
                _progressValue = i * 10
                Thread.Sleep(1000)
            
Next

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

    End Sub

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

        
' プログレスバー更新
        Me.progressBar1.Value = _progressValue

    
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();

            
// プログレス更新タイマー開始
            timer1.Interval = 200;
            timer1.Enabled = 
true;
        }

        
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)
        {
            
if (_thread != null)
            {
                
// スレッドを強制終了させる
                _thread.Abort();

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

        
// スレッド処理
        private void ThreadProc()
        {
            
try
            {
                
for (int i = 0; i <= 10; i++)
                {
                    
// プログレスの値加算
                    _progressValue = i * 10;
                    
Thread.Sleep(1000);
                }
            }
            
catch (ThreadAbortException ex)
            {
                
Console.WriteLine("スレッド強制終了!");
            }
        }

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

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




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

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