- PR -

Windowsサービスで処理が実行されない

1
投稿者投稿内容
カウンター
大ベテラン
会議室デビュー日: 2004/02/19
投稿数: 123
投稿日時: 2006-12-16 19:25
VB.netでWindowsサービスを作成してインストールしました。

ざっくりとした処理の概要としては
・サービス起動時にタイマーを5つ起動
・タイマーによって起動される処理でテキストファイルの読み書き

コンピュータの管理画面で作成したサービスが起動しているのは確認できたのですが
OnStartに書いてある処理が動いた形跡がありません。(ログファイルにて確認)

サービスとして作ったコードをWindowsアプリケーションに移して実行したところ
タイマーが起動してその後の処理も起動しました。

サービスはDebugでビルド、プロジェクトのスタートアップはSub Main()です。

OnStartに書いたコードは以下の通りです。
コード:
Try

'--- ログファイル出力
・・・省略
            '---タイマー1
            AddHandler zantimer.Elapsed, New System.Timers.ElapsedEventHandler(AddressOf zantimer_Elapsed)
            zantimer.Interval = fnc01
            zantimer.AutoReset = True
            zantimer.Enabled = True
            'zantimer.Start()


            '---タイマー2
            AddHandler kestimer.Elapsed, New System.Timers.ElapsedEventHandler(AddressOf kestimer_Elapsed)
            kestimer.Interval = fnc02
            kestimer.AutoReset = True
            kestimer.Enabled = True
            'kestimer.Start()


            '---タイマー3
            AddHandler faxtimer.Elapsed, New System.Timers.ElapsedEventHandler(AddressOf faxtimer_Elapsed)
            faxtimer.Interval = fnc03
            faxtimer.AutoReset = True
            faxtimer.Enabled = True
            'faxtimer.Start()


            '---タイマー4
            AddHandler banktimer.Elapsed, New System.Timers.ElapsedEventHandler(AddressOf banktimer_Elapsed)
            banktimer.Interval = fnc04
            banktimer.AutoReset = True
            banktimer.Enabled = True
            'banktimer.Start()
            
            '---タイマー5
            AddHandler backtimer.Elapsed, New System.Timers.ElapsedEventHandler(AddressOf backtimer_Elapsed)
            backtimer.Interval = fnc05
            backtimer.AutoReset = True
            backtimer.Enabled = True
            'backtimer.Start()

            Return True

        Catch ex As Exception
            Me.OnStop()
        End Try



Windowsサービスでのタイマーの使いかたはWindowsアプリケーションとは違うのでしょうか?

それとも、根本的にWindowsサービスの作成方法で何か間違っているのでしょうか?
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-12-16 23:05
引用:

Windowsサービスでのタイマーの使いかたはWindowsアプリケーションとは違うのでしょうか?



Windows.Forms の Tiemr は使っちゃ駄目です。

標準ライブラリには Timer が3つくらいあるはずですが、どの Timer を使ったのでしょうか?
カウンター
大ベテラン
会議室デビュー日: 2004/02/19
投稿数: 123
投稿日時: 2006-12-17 00:13
渋木宏明さん。こんばんは。

引用:


Windows.Forms の Tiemr は使っちゃ駄目です。

標準ライブラリには Timer が3つくらいあるはずですが、どの Timer を使ったのでしょうか?




System.Timers.Timerを使っています。
コードをWindowsアプリに移してテストした際にもSystem.Timers.Timerを使用して
タイマーは起動しました。
k_kazu
常連さん
会議室デビュー日: 2006/02/11
投稿数: 25
投稿日時: 2006-12-17 01:37
引用:

System.Timers.Timerを使っています。



タイマーオブジェクトの生成と破棄のコーディングに問題はありませんか?
System.Timers.Timer のサンプルコード
http://msdn2.microsoft.com/ja-jp/library/system.timers.timer(VS.80).aspx
ではタイマーオブジェクトがガーベージコレクションされないように
GC.KeepAlive(aTimer);
としていますが 、タイマーオブジェクトがガーベージコレクションの対象にならないように工夫していますか?

Windowsサービスと、Windowsアプリケーションは実行するスレッドモードが
違うので(STAThread と MTAThread)Windowsアプリでは動いてWindowsサービスでは動かないという現象になっているのかもしれません。

また、サポート技術情報でこういうのがありました。
[BUG] Windows サービスで System.Timers.Timer クラスの Elapsed イベントが発生しない
http://support.microsoft.com/kb/842793/ja

また、System.Threading.Timer でも
[FIX] .NET Framework ベースのアプリケーションで System.Threading.Timer クラスを使用すると、.NET Framework 1.1 SP1 でタイマ イベントが通知されないことがある
http://support.microsoft.com/kb/900822/

ちなみに、私の場合はサービスでTimerイベントは使った事がありません。
いつもはループと Thread.Sleep() の組み合わせで定期的な処理を行っています。
5つのタイマーを使うと、数個のスレッドから同時アクセスされることを考慮した
コーディングが必要となり、テストも大変だと思います。
機能的に独立した複数のスレッドを起動することはありますが、機能が密接に関連する
定期的な処理は1つのスレッドで順番に実行することでコーディングとテストが
かなり簡略化されます。
カウンター
大ベテラン
会議室デビュー日: 2004/02/19
投稿数: 123
投稿日時: 2006-12-17 02:36
引用:

k_kazuさんの書き込み (2006-12-17 01:37) より:

タイマーオブジェクトの生成と破棄のコーディングに問題はありませんか?
System.Timers.Timer のサンプルコード
http://msdn2.microsoft.com/ja-jp/library/system.timers.timer(VS.80).aspx
ではタイマーオブジェクトがガーベージコレクションされないように
GC.KeepAlive(aTimer);
としていますが 、タイマーオブジェクトがガーベージコレクションの対象にならないように工夫していますか?

Windowsサービスと、Windowsアプリケーションは実行するスレッドモードが
違うので(STAThread と MTAThread)Windowsアプリでは動いてWindowsサービスでは動かないという現象になっているのかもしれません。



ガベージコレクションの対象になるかどうかは、考慮していませんでした。
考慮した作りにすることも選択肢の一つとして残しますが、
ちょうど、k_kazuさんが教えてくれた、以下のレポートを読んでいたところでした。

引用:

また、サポート技術情報でこういうのがありました。
[BUG] Windows サービスで System.Timers.Timer クラスの Elapsed イベントが発生しない
http://support.microsoft.com/kb/842793/ja

また、System.Threading.Timer でも
[FIX] .NET Framework ベースのアプリケーションで System.Threading.Timer クラスを使用すると、.NET Framework 1.1 SP1 でタイマ イベントが通知されないことがある
http://support.microsoft.com/kb/900822/



動かない原因はこのレポートと同じ原因なのかと考えていたところです。

引用:

ちなみに、私の場合はサービスでTimerイベントは使った事がありません。
いつもはループと Thread.Sleep() の組み合わせで定期的な処理を行っています。
5つのタイマーを使うと、数個のスレッドから同時アクセスされることを考慮した
コーディングが必要となり、テストも大変だと思います。
機能的に独立した複数のスレッドを起動することはありますが、機能が密接に関連する
定期的な処理は1つのスレッドで順番に実行することでコーディングとテストが
かなり簡略化されます。



たしかに、タイマーが5つあるのは現実的ではないような気はしてました。
Windosサービスの作成もタイマーを複数使ったプログラムの作成も今回が初めてだったので
いまさら(締め切り間近(汗))になって、まずい気がしています(´ヘ`;)

今回のサービスはパソコンが起動しいる間は常に、タイマーで5つの処理をキックしているのですが
ループと Thread.Sleep() を使う方法とは、具体的にどんな感じでしょうか?
無限ループを使うということですか?
例えば、何分おきにある処理をキックするサンプルコードを教えていただけますでしょうか?

よろしくお願いします。

カウンター
大ベテラン
会議室デビュー日: 2004/02/19
投稿数: 123
投稿日時: 2006-12-20 09:54
Windowsサービスでのタイマー起動ですが

単純にタイマーの実装が間違っていただけで、正しく実装したらタイマー起動しました。

動かない時は、サービスプロジェクトに追加したモジュールでタイマーのインスタンスを作成していましたが
サービスの『Private components As System.ComponentModel.IContainer』でタイマーインスタンスを作成するのが正解でした。

コード:

Private components As System.ComponentModel.IContainer

' メモ : 以下のプロシージャはコンポーネント デザイナで必要です。
' コンポーネント デザイナを使って変更できます。
' コード エディタを使って変更しないでください。
Friend WithEvents Timer1 As System.Timers.Timer
Friend WithEvents Timer2 As System.Timers.Timer
Friend WithEvents Timer3 As System.Timers.Timer
Friend WithEvents Timer4 As System.Timers.Timer
Friend WithEvents Timer5 As System.Timers.Timer
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Timer1 = New System.Timers.Timer
Me.Timer2 = New System.Timers.Timer
Me.Timer3 = New System.Timers.Timer
Me.Timer4 = New System.Timers.Timer
Me.Timer5 = New System.Timers.Timer
CType(Me.Timer1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.Timer2, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.Timer3, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.Timer4, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.Timer5, System.ComponentModel.ISupportInitialize).BeginInit()
'
'Timer1
'
Me.Timer1.Enabled = False
'
'Timer2
'
Me.Timer2.Enabled = False
'
'Timer3
'
Me.Timer3.Enabled = False
'
'Timer4
'
Me.Timer4.Enabled = False
'
'Timer5
'
Me.Timer5.Enabled = False
'
'CBGW01
'
Me.CanPauseAndContinue = True
Me.ServiceName = "CBGW01"
CType(Me.Timer1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.Timer2, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.Timer3, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.Timer4, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.Timer5, System.ComponentModel.ISupportInitialize).EndInit()

End Sub



k_kazuさん、渋木宏明さん、ありがとうございました。

[ メッセージ編集済み 編集者: カウンター 編集日時 2006-12-20 10:04 ]
1

スキルアップ/キャリアアップ(JOB@IT)