アクセス数 累計:000,125,043 昨日:000,000,099 本日:000,000,065
|
|
|
|
【Amazon ランキング:本 - コンピュータ・IT】
|
|
前の回で作成したスレッドプログラムで多重起動は防止できるようになったと思いますがデバッグモードで実行している時に画面が閉じているのにまだ実行されているという現象は発生しなかったでしょうか?
スレッドを開始してプログレスバーが動いている途中で画面を閉じるとその現象が発生するのですが、その理由は左図の通りです。
メインスレッドから起動されたサブスレッドは画面が閉じても動き続けていて、アプリケーションはサブスレッドが終了するまで動き続けるからです。
スレッドプログラミングをするにあたりこのような状態が発生すること常に意識しておかないと画面を閉じたにプロセスが生きたままになっていて思わぬ障害を引き起こしかねません。
この回ではこのような状態を回避する方法を解説したいと思います。 |
|
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 Object, ByVal 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. |
|
|
|