C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

タイマーオブジェクトの挙動に関して /k3user (19/02/06(Wed) 15:50) #90078
Re[1]: タイマーオブジェクトの挙動に関して /k3user (19/02/06(Wed) 16:39) #90079 解決済み
Re[1]: タイマーオブジェクトの挙動に関して /魔界の仮面弁士 (19/02/06(Wed) 16:58) #90080


親記事 / ▼[ 90079 ] ▼[ 90080 ]
■90078 / 親階層)  タイマーオブジェクトの挙動に関して
□投稿者/ k3user (68回)-(2019/02/06(Wed) 15:50:33)

分類:[.NET 全般] 

タイマーオブジェクトを作成して定期的にある関数を呼ぶような
プログラムを作成しているのですが、Form1クラスのMsgBox("test")
を実行するとTestTimerクラスのlfExecProcメソッドを数十回(1秒もかからない間隔で)と
勝手に処理されてしまいます。TestTimerクラスのlvObjTmrを破棄すれば
問題は解決しますが、なぜこのような現象が起こるかが不明です。
明確な原因等をご教示ください。


以下に作成した環境とプログラムを簡略化したもの(ビルド、実行可)
記載しました。

●環境
OS      :Windows10
開発環境:Visual Studio2015

●TestFormのプロジェクト設定
対象のフレームワーク  :.NET Framework4.6
アプリケーションの種類 :Windowsフォームアプリケーション
対象のCPU       :AnyCPU
32ビットを優先にチェック
参照DLL        :TestTimerDll.dllならびにsystem.*関連
ソース         :Form1.vbのみ(画面にButtonを配置しているのみ)

*******************************************
Form1.vbの内容
*******************************************

Public Class Form1
    Private objTm As TestTimerDll.TestTimer
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        System.Windows.Forms.Application.DoEvents()
        objTm = New TestTimerDll.TestTimer
        If objTm.testFunction() = True Then
            objTm.timerSet()
        Else
            If objTm.testFunction() = False Then
                MsgBox("test")
                Me.Close()
            End If
        End If
    End Sub
End Class

●TestTimerDllのプロジェクト設定
対象のフレームワーク  :.NET Framework4.6
アプリケーションの種類 :Windowsフォームアプリケーション
対象のCPU       :AnyCPU
32ビットを優先にチェック
参照DLL        :system.*関連(DrawingとFormを追加)
ソース         :TestTimer.vbとfmXXTimer.vb

*******************************************
TestTimer.vbの内容
*******************************************
Public Class TestTimer

    Private WithEvents lvObjTmr As New fmXXTimer

    Public Sub New()
        MyBase.New()
    End Sub

    Public Function timerSet() As Boolean
        lvObjTmr.tmrExe.Interval = 2000
        Return True
    End Function

    Public Function testFunction() As Boolean
        Return False
    End Function

    Private Function lfExecProc() As Boolean
        Dim test As String
        test = ""
        Return True
    End Function

    Private Sub lvObjTmr_GoExe() Handles lvObjTmr.GoExe
        Call lfExecProc()
    End Sub

End Class


*******************************************
fmXXTimer.vbの内容
*******************************************

Option Strict Off
Option Explicit On
Friend Class fmXXTimer
	Inherits System.Windows.Forms.Form
	
	Public Event GoExe()

	Private Sub fmXXTimer_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
		tmrExe.Interval = 0
	End Sub
	Private Sub Form_Terminate_Renamed()
	        tmrExe.Interval = 0
	End Sub
	Private Sub fmXXTimer_FormClosed(ByVal eventSender As System.Object, ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
	        tmrExe.Interval = 0
	End Sub
	Private Sub tmrExe_Tick(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles tmrExe.Tick
	        RaiseEvent GoExe()
	End Sub
End Class



[ □ Tree ] 返信 編集キー/

▲[ 90078 ] / 返信無し
■90079 / 1階層)  Re[1]: タイマーオブジェクトの挙動に関して
□投稿者/ k3user (70回)-(2019/02/06(Wed) 16:39:58)
申し訳ございません。
プログラム自体に問題がありましたので、解決済みとさせてください。
お騒がせしてしまい申し訳ございませんでした。
解決済み
[ 親 90078 / □ Tree ] 返信 編集キー/

▲[ 90078 ] / 返信無し
■90080 / 1階層)  Re[1]: タイマーオブジェクトの挙動に関して
□投稿者/ 魔界の仮面弁士 (2039回)-(2019/02/06(Wed) 16:58:57)
No90078 (k3user さん) に返信
> タイマーオブジェクトを作成して

ここでいうタイマーとは、下記の 1 のことですね?

1) System.Windows.Forms.Timer クラス
2) System.Threading.Timer クラス
3) System.Timers.Timer クラス
4) System.Windows.Threading.DispatcherTimer クラス


DLL 側のプロジェクトで、fmXXTimer.vb をデザイナで開き、
tmrExe の初期設定で
 Enabled = True
 Interval = 1 以上の値
に設定されていたりしないか、確認してみてください。



> 定期的にある関数を呼ぶような

1 は UI スレッドで動くタイマーなので、
Tick イベントの発生のために、メッセージループが必要です。

メッセージループを回す処理としては、下記のような物があります。
 Applicarion.Run メソッド
 Applicarion.DoEvents メソッド
 Form.ShowDialog メソッド
 MessageBox.Show メソッド / MsgBox 関数



> Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
>   System.Windows.Forms.Application.DoEvents()

ここで DoEvents を呼んでいるのは、何を目的としたものでしょうか?


>   If objTm.testFunction() = True Then
>     objTm.timerSet()
>   Else

提示頂いたコードでは、timerSet メソッドが呼び出されることはありませんし、
fmXXTimer の Load イベントに到達することも無いので、
tmrExe の Interval が 0 や 2000 に書き換われることは無く、
デザイン時の初期値を維持しているはずです。



> TestTimerクラスのlvObjTmrを破棄すれば

そもそものクラス設計に問題があるような。

Form も Timer も IDisposable なオブジェクトなので、寿命管理が必要なはずですが、
TestTimer クラスは IDisposable パターンとして実装されていないように見えますし、
明示的な破棄に必要な処理も組み込まれていないように見えます。


tmrExe については、fmXXTimer が Dispose された時に、
fmXXTimer.designer.vb 側の Dispose(Boolean) を通じて破棄されますが、
TestTimer 側には、その fmXXTimer を破棄するためのコードが無いので、
GC 任せになってしまっていますよね。
[ 親 90078 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -